Parcel 2 alpha 1 is here!

Parcel 2.0.0-alpha.1 is here!

Today I’m incredibly excited to release the first alpha version of Parcel 2! Please try it out and help us take Parcel 2 to the finish line. Check it out on Github!

Parcel 2 is a ground up rewrite of Parcel that we’ve been working on for over a year, and designing for almost a year before that. It incorporates everything we’ve learned building Parcel since the beginning, and the result is more extensible, scalable, and reliable than Parcel 1, while retaining the ease of use and developer experience you’ve come to expect from Parcel.


Parcel famously requires zero configuration. This never meant non-configurable, just that Parcel attempted to infer as much as possible from the code itself, and used existing config files for other tools (e.g. .babelrc). Users have loved the ease of use and developer experience that this has provided, but there are always edge cases and real use cases that require a bit more customizability.

Parcel 2 is optionally configurable. The default config built into the Parcel 2 CLI will be enough for the majority of apps and includes everything Parcel 1 supported and more, but Parcel 2 supports extending the core with additional functionality through a complete set of plugin types designed specifically for each of Parcel’s core stages.

All of these are configured in a very simple JSON file called .parcelrc. There is no JavaScript or complex logic required to configure Parcel, if you ever need to at all. You can also extend other configs, and share them as npm packages. We expect that most configs will extend the @parcel/config-default package to add or override some of the built-in defaults as needed.

For example, here’s how you’d add a transform for Dart to your app once you’ve published the parcel-transform-dart package.

  "extends": ["[@parcel/config-default]("],
  "transforms": {
    "*.dart": ["parcel-transform-dart"],

Small Core

Now that everything in Parcel is split out into plugins, Parcel core is incredibly small. It now essentially just runs other tools as needed based on a graph of the files in your application, in a very intentional and optimized way. Everything is designed to be done in parallel and be cacheable, both locally and eventually, across machines.

Parcel maintains a highly optimized graph of your entire application, which can be invalidated super granularly to trigger rebuilds of only exactly what is needed when things change. This includes both your code, and everything that influences how that code is built, such as config files (e.g. .babelrc), plugin versions, and more. The whole graph is cached on disk when Parcel stops, and can be restored on startup and invalidated granularly so that only files that changed are rebuilt. It’s just like watch mode, but even when Parcel is restarted!

A Parcel asset graph, showing a build with multiple targets (see below).A Parcel asset graph, showing a build with multiple targets (see below).

The worker farm has been updated to make use of the new worker_threads module built into Node 12 when available, which has lower overhead than the multi-process backend used in previous versions. Additionally, we’ve abstracted all filesystem access in Parcel so that it is pluggable with different filesystem implementations. For example, you might want to use an in memory filesystem to run Parcel in the browser.

Multiple targets, and bundle splitting

Aside from a completely new core and plugin system, Parcel 2 also has a bunch of new features, including support for multiple targets, and bundle splitting.

Parcel 2 allows you to configure builds for multiple targets, which will be built in parallel. For example, you may want to build a version of your application for modern browsers with modern syntax, and one for legacy browsers with more transpilation. Or maybe you want to build a library for both node and the browser. Now you can do that and more, by configuring targets in your package.json.

The following example will result in two complete builds, compiled for a recent Chrome version, and more legacy browsers. These can then be loaded with differential loading techniques to decrease bundle sizes for modern browsers.

  "browser": "dist/legacy/index.js",
  "browserModern": "dist/modern/index.js",
  "targets": {
    "browserModern": {
      "engines": {
        "browsers": [
          "last 1 Chrome version"
    "browser": {
      "engines": {
        "browsers": [
          "> 0.25%"

In local development, we avoid this extra work by compiling for a default modern browser target, for performance. This means that Babel and other tools need to do less work to transpile your code, when you’re just testing in Chrome. If you need to test a specific target (e.g. an old browser like IE 11), you can choose to build for that target with the --target option to the CLI.

Parcel 2 also supports advanced bundle optimizations, which automatically split out common dependencies like react and other libraries into their own bundles that can be loaded in parallel and cached separately from the rest of your code. This should result in smaller initial bundle sizes than Parcel 1, because it no longer hoists common dependencies to the top of the tree when they aren’t needed by the entry bundle.

Whole application bundling

From the beginning, Parcel went farther than many other tools in bundling your whole application, including JavaScript, CSS, HTML, and static assets. Most other bundlers are still very JavaScript focused, and convert all asset types to JS, possibly with additional plugins to extract them again later. Parcel is file type agnostic, and Parcel 2 takes this even further by allowing you to override and compose every aspect how your code is processed.

Parcel 2 plugins are organized into pipelines, which can be composed very easily to specify advanced transformations and build steps. Assets match an initial pipeline by a glob, and run through all of the plugins in that pipeline until the file type changes (e.g. .ts → .js). Then, they continue through the next pipeline, and so on until the end of a pipeline is reached. This allows individual plugins to focus on a single task, and lets the user compose multiple plugins together to do something more complex.

Transformations can also output multiple assets, in case there are inline assets of a different type, such as an inline