📦 Parcel v1.9.0 — Tree Shaking, 2x faster watcher, and more! 🚀

Today I’m super excited to release Parcel v1.9.0, a huge release including some awesome features! Check it out on Github.

The highlights of this release include:

  • 🌳 Tree Shaking for both ES6 and CommonJS modules — Parcel now removes unused code from your production bundles by completely compiling away the module system, reducing the file sizes and initialization times of bundles considerably.
  • 👀 Up to 2x faster file watcher — Parcel’s file watcher now runs in a background worker for performance and stability. This speeds up compilation times during development by up to 2x!
  • 💵 Resolved filenames are now cached — Parcel caches the resolved module names along with the compiled code, which makes rebuilds much faster. This means that when you e.g. import 'react', it doesn’t need to resolve that module to e.g. /my-project/node_modules/react/index.js every time you do a build.
  • 🔎 Extended resolver for SASS, LESS, and Stylus — Parcel has supported SASS, LESS, and Stylus since the beginning, but now supports extended importing syntax in line with the rest of Parcel. For example, you can now import from node_modules, and use ~/tilde and /absolute paths as well.
  • 🚨 Improved browser error reporter — Parcel’s error reporter now shows syntax errors and other compilation errors right in your browser when you reload. No need to go back to the terminal to see what you did wrong!
  • 💪 Many bugfixes and improvements!

Huge thanks to everyone who contributed to this release! 🙏

Tree Shaking

The biggest new feature in Parcel v1.9.0 is tree shaking! This has been a months long project to rebuild some of our core infrastructure with tree shaking in mind. Parcel now completely compiles away the module system, hoisting all modules into the same top-level scope, leaving unused code from large libraries out of your production bundles. 🍃

In contrast to other bundlers, Parcel supports tree shaking for both ES6 and CommonJS modules! This is a HUGE deal, since most of the code in libraries on npm is still CommonJS. Other tools have focused on tree shaking for ES6 since it is much easier to statically analyze, but in order to truly have a big impact on most apps, we need to analyze CommonJS dependencies as well.

Most of the work Parcel does when tree shaking is also done in parallel using our worker processes, and is also cached on the filesystem, just like Parcel has always done. This means that builds are still fast, and rebuilds are like lightning. ⚡️

Parcel’s tree shaking implementation works in four phases:

  1. The hoisting phase — this happens on each individual file, in parallel background workers. In this phase, Parcel renames all of the top-level variables to be unique so they won’t clash with variables from other modules, and produces some metadata about the symbols that are imported and exported from the module.
  2. The concatenation phase — once all of the files have been processed, Parcel concatenates the modules together in the right order. This takes into account edge cases possible especially in CommonJS like circular dependencies, side effect ordering, nested requires, and more. This produces a single file with all of the code in the bundle.
  3. The linking phase — once it has concatenated the files in the right order, Parcel uses the metadata produced in the hoisting phase to link together the imports and exports from each module. This handles interoperability between CommonJS and ES6, so you can import a CommonJS file, or require an ES6 module just as you would expect.
  4. The elimination phase — in this phase, unused declarations are removed, and the top-level variables are mangled. Most of the minification actually happens at the file level, just after the hoisting phase. The only things left are to remove declarations in the top-level scope that weren’t used across modules, and to minify the remaining top-level variable names.

The below image shows how Parcel’s tree shaking removes unused exports, and renames variables so that they don’t conflict with other modules. The output bundle also has no module wrapper functions, just a single IIFE wrapping the entire bundle, for truly zero cost modules.

Parcel also supports the sideEffects: false flag in package.json as well, which lets library authors tell Parcel and other bundlers that they contain no side effects during initialization, allowing us to be much more efficient about what code we include. Large libraries like lodash have made good use of this feature to reduce bundle sizes by excluding all functions that aren’t used.

I’ve been testing out Parcel’s tree shaking implementation on a bunch of different applications with some very good results. Obviously, the impact that tree shaking will have on your code depends on how optimized your bundle already is. Here are some file size differences from the previous version for apps of various sizes:

  • import {clone} from 'lodash-es': 97% smaller (399 KB → 13 KB)
  • vue-hackernews: 20% smaller (369 KB → 298 KB)
  • Large work app: 9% smaller (2.28MB → 2.08MB)

We’re launching tree shaking as an experimental feature in Parcel v1.9.0 since we want to be sure it works really well on lots of real world apps before enabling it by default in production. You can try it out today using the --experimental-scope-hoisting option to the parcel build command. Please help us out and report any bugs you find! 🐞

HUGE thanks to Fathy Boundjadj for his help implementing this feature! Given his hard work on this feature and many others, Fathy earned merge rights to Parcel as a maintainer last month. Congrats! 🎉

Faster File Watcher

One of the reasons Parcel’s development experience is so nice is its fast recompilation of modules as you develop. It turned out, however, that there was a cost to running the watcher on large apps with thousands of files.

Parcel v1.9.0 moves the file watcher into a background worker, for performance and stability. This means that the main Parcel process can focus on building code without also watching files at the same time. This has a HUGE impact on the build performance of Parcel, especially on Windows.

My large work project’s development build time was cut in HALF by this change. In addition, things are much more stable — less crashes with strange error messages from the operating system (the new background worker automatically restarts when this happens).

Thanks to Jasper DeMoor for working on this feature. Jasper has been contributing to Parcel since the beginnging, and also joined Fathy as a maintainer last month. Congrats!🏅

Try it out!

I’m really excited about this release, and I can’t wait to see what you build with it!

Please report any bugs you find on Github. You can also find me @devongovett on Twitter.