2018 is a great year for JavaScript and development in general! The clientside framework options abound with Vue, Angular, and React.

Serverside options include Koa, vanilla Node, Express, Hapi, Total, Restify, and AWS Lambda.

To top it all off, the coterminous developments in build and transpilation tools have significantly widened the field. While, old timers like Gulp, Grunt, and Browserify remain relevant, we'll take a close look at Parcel, Rollup, and the newly released webpack 4!

Shared Dependencies

OK, let's set up our package.json by adding Babel, which will be used, in some capacity, by each of the three tested build tools:

Shared babel dependencies:

    "babel-loader": "=7.1.4",
    "babel-plugin-external-helpers": "=6.22.0",
    "babel-preset-env": "=1.6.1",
    "babel-preset-react": "=6.24.1",
    "babel-preset-stage-0": "=6.24.1"

Babel provides transpilation support for translating newer ES6 and ES7 syntax into 2018 web-browser compliant ES5. Babel provides this support for other JavaScript dialects through babel-presets along with polyfills and shims.

Once we've added Babel, we need to supplement our project with the following .babelrc in our project root:

{
  "presets": ["env", "react", "stage-0"]
}

Parcel

Parcel was recently released and provides an incredibly light-weight, almost configuration-free, build tool. We add the following parcel dependencies to our package.json:

    "parcel-bundler": "=1.7.1"

The core difference here between Parcel and webpack 4 is that we directly set the index.js file into the script.scr of our index.html or view rather than the compiled bundle.

In other words, we would put:

    <script src="../reactAppSrc/index.js"></script>

Rather than:

    <script src="built/vendor.min.js"></script>
    <script src="built/built.min.js"></script>

We can then run the following command to transpile our dependencies:

$ parcel index.html

For production builds:

$ parcel build public/parcel.index.html

The magic behind Parcel is that it will automatically build a dependency and script tree then proceed to transpile, minify, and bundle those assets as needed without any human configuration required.

Parcel also caches both its build processes, vastly decreasing build time on subsequent runs.

Rollup

Rollup represents another recent addition and alternative. Users who've used webpack will find Rollup's configuration familiar and easy to set up:

We add the following Rollup dependencies:

    "rollup": "=0.58.2",
    "rollup-plugin-babel": "=3.0.4",
    "rollup-plugin-uglify": "=3.0.0"

For Development:

$ rollup -c rollup/rollup.dev.config.js --external all
import babel from 'rollup-plugin-babel';

export default {
  entry: 'reactAppSrc/rollup.index.js',
  dest: 'public/built/main.min.js',
  format: 'iife',
  plugins: [
    babel({
      babelrc: false,
      exclude: 'node_modules/**',
      presets: [
        "react",

        [
          "es2015",
          {
            "modules": false
          }
        ]
      ],
      "plugins": [
        "external-helpers"
      ]
    })
  ],
};

For Production:

$ rollup -c rollup/rollup.prod.config.js --external all
import babel from 'rollup-plugin-babel';
import uglify from 'rollup-plugin-uglify'

export default {
  entry: 'reactAppSrc/rollup.index.js',
  dest: 'public/built/main.min.js',
  format: 'iife',
  sourceMap: 'inline',
  plugins: [
    babel({
      babelrc: false,
      exclude: 'node_modules/**',
      presets: [
        "react",

        [
          "es2015",
          {
            "modules": false
          }
        ]
      ],
      "plugins": [
        "external-helpers"
      ]
    }),
    uglify()
  ],
};

webpack 4

webpack dependencies:

    "webpack": "=4.6.0",
    "webpack-cli": "=2.0.15"

The release of webpack 4 continues to see significant improvements and simplified configuration:

'use strict'

const path = require('path'),
  webpack = require('webpack')

module.exports = {
  mode: 'production',
  entry: './reactAppSrc/index.js',
  output: {
    path: path.resolve(__dirname, '../public/built/'),
    filename: '[name].min.js',
  },
  resolve: {
    extensions: ['.js', '.jsx'],
  },
  module: {
    rules: [
      {
        test: /\.jsx$/,
        exclude: /node_modules/,
        loader: 'babel-loader'
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader'
      }
    ]
  },
  plugins: []
}

Here, we just need to switch the mode attribute by running one of the following two commands:

$ webpack --config webpack/webpack.dev.config.js --progress --profile --colors
$ webpack --config webpack/webpack.prod.config.js --progress --profile --colors

Testing

All three libraries were tested and built on the following Dell 15 XPS 2016 with specs:

    Intel Core i7-6700HQ Quad-Core (8 Logical Cores) at 2.60 GHz
    32 GB RAM
    Windows 10 Pro + Linux Subsystem and Cygwin
    NVIDIA 960M GPU
    256GB m2 PCIe SSD
    15.6" FHD Screen

Results divided into Development and Production modes:

Tool Dev Build Time One Dev Build Time Two Dev Build Time Three Dev Build Time Avg
Parcel 14.92 s 5.22 s 4.36 s 8.16 avg s
Rollup 0.570 s 0.482 s 0.487 s 0.513 avg s
Webpack 3.608 s 3.328 s 3.844 s 3.59 avg s

Best: Rollup (0.513 avg s)

Production mode:

Tool Prod Build Time One Prod Build Time Two Prod Build Time Three Prod Build Time Avg
Parcel 738.509 s 35.364 s 35.592 s 269.82 avg s
Rollup 0.712 s 0.665 s 0.714 s 0.697 avg s
Webpack 3.636 s 3.805 s 4.305 s 3.915 avg s

Best: Rollup (0.697 avg s)

Other Considerations

Above, we compare raw build time alone, but there are several other highly relevant considerations:

  1. Parcel's caching feature sees dramatically decreases in time consumption after the initial run. For frequent, small changes, in smaller projects **Parcel*8 is a great choice.
  2. Rollup provides much simpler configuration over webpack 4 and has a host of pre-configured plugins that are a breeze to incorporate into your project. Rollup's also the fastest of the build tools period.
  3. Rollup also provides convenient source maps, which can aid in debugging.
  4. webpack 4 has gotten a lot easier to use and particularly through the convenient mode attribute (which will enforce minification when set to 'production' automatically now).

Takeaways

Overall, Parcel's a fantastic choice for small projects since it requires zero configuration.

webpack 4 represents a great improvement in the tradition of a tried and true workhorse. It's also largely interchangeable with webpack 3 configuration which simplifies migration.

The big winner is Rollup which represents the next generation of build tools in terms of its performance (build time), intermediate configuration (less complicated than webpack but more involved than Parcel), and optional but out-of-the-box features likes source maps, and not using a .babelrc.

For brand new projects, I'd strongly encourage taking a look at Rollup!

Check out GitHub for the all the code used in this article!