In my demo project I have examples of how to bundle Angular applications with pretty much any bundler under the sun. Today I added Parcel to the collection. Let’s see how it compares to one of my existing Webpack configurations.

The focus of this experiment is mainly on production bundle size. This means I will ignore the time it takes to generate the bundle. Bundling times are of course very important for developer environments, but I will save that discussion for a later post, perhaps.

The demo application used for this post is the usual benchmark application from my Github repo.

Now, let’s compare Parcel and Webpack.

Parcel

I had read about Parcel a little while ago, but couldn’t find the time to give it a try.

Looking back, lack of time was not a good excuse for putting Parcel off. Including reading enough of the documentation, it took me all of five minutes to generate a production bundle with Parcel.

All you have to do to make it work is to download the npm package and run a single command against the entry point of your application.

Usually there is at least some level of configuration to fight with before it works, but with Parcel it just works.

parcel build built-es6/app/main.js --out-dir dist/parcel-bundle

Here’s the command I ran:

This setup assumes an AoT compiled Angular application, which I already have from a shared setup between my different bundling samples.

Basically all I do is this:

ngc -p tsconfig-es6.json

Webpack

Webpack is still one of my favorite bundlers. Not only is it backed by a huge community, it also offers lots of flexible options.

The flexibility is both a blessing and a curse though.

It’s great to be able to make very targeted framework specific decisions, but the price you pay is potentially complicated configuration.

Here is the config I used for this sample:

const UglifyJsPlugin = require('webpack/lib/optimize/UglifyJsPlugin'); const PurifyPlugin = require('@angular-devkit/build-optimizer').PurifyPlugin; const webpack = require('webpack'); module.exports = { entry: './built-es5/app/main.js', output: { filename: 'dist/bundle-webpack-3-no-lazy-loading.js' }, module: { rules: [ { test: /\.js$/, loader: '@angular-devkit/build-optimizer/webpack-loader', options: { sourceMap: false } } ] }, plugins: [ new webpack.optimize.ModuleConcatenationPlugin(), new UglifyJsPlugin({ beautify: false, output: { comments: false }, mangle: { screw_ie8: true }, compress: { screw_ie8: true, warnings: false, conditionals: true, unused: true, comparisons: true, sequences: true, dead_code: true, evaluate: true, if_return: true, join_vars: true, negate_iife: false }, }), new PurifyPlugin() ] }

To make it interesting I turned on all the Webpack optimizations I’m aware of, even some specific to Angular bundling.

Here we have ModuleConcatenationPlugin for better scope hoisting, PurifyPlugin for better Angular code removal, and Uglify for minification.

Comparing the Results

For a side by side comparison, I have deployed both versions of the application here:

How do bundle sizes compare?

What we see is that the current configurations yield a much smaller Webpack bundle. As a result of all the Webpack optimizations I am able to squeeze it down to 126k vs 186k with Parcel.

This is a difference of 60k (48%), which is pretty substantial. Granted, we owe a lot of this difference to Angular specific optimizations unavailable to Parcel.

To add one more datapoint I added a Rollup version as well. It weighed in at 149k. This version doesn’t do anything specific to Angular, so it’s more framework optimization agnostic.

Generally you would expect Rollup to be smaller than Webpack, but Angular specific optimizations in Webpack will throw this off.

Based on feedback from readers I decided to add a Webpack version without Angular optimizations. As expected this reduced the difference quite a bit, but the Webpack bundle is still smaller at 155k. I have deployed that version here.

Still, I really like the simplicity of Parcel. I think there is room for improvement, but I am very impressed with how easy it is to get started.

However, I think the no configuration approach suffers a bit when it comes to framework specific fine tuning. Maybe Parcel should consider some light configuration, or an Angular command line switch?

In case you are interested in looking at comparisons between other bundlers as well, I have added a more comprehensive bundler comparison here.