## 1. Project Overview & Quickstart (parcel-bundler/app.c9a6fe.js)

# app.c9a6fe.js

Open-source repository parcel-bundler/app.c9a6fe.js

### Repository Details
- **Repository:** [parcel-bundler/app.c9a6fe.js](https://github.com/parcel-bundler/app.c9a6fe.js)
- **Primary Language:** Code

*Note: High-volume repository documentation is actively indexed and synchronized by YakaAI.*

## 2. Official Technical Reference & Guides (parcel-bundler/website)

## File: README.md

# 🌎 Parcel 2 website

This is the website for Parcel v2. Please help us out by giving your feedback in issues, and feel free to send pull requests for contributions. 😍

## Contributing

Start a local server using:

```bash
yarn
yarn serve
```

The website is automatically deployed using [Vercel](https://vercel.com).

Search is powered by [Algolia DocSearch](https://docsearch.algolia.com/).

---

## File: package.json

{
  "name": "parcel-website",
  "version": "0.0.0",
  "private": true,
  "license": "MIT",
  "workspaces": [
    "packages/*"
  ],
  "browserslist": [
    "last 2 Safari versions",
    "last 2 Chrome versions",
    "last 2 Firefox versions"
  ],
  "scripts": {
    "build": "rm -rf _site dist; eleventy; parcel build src/home/index.html '_site/*.html' _site/*/index.html '_site/*/*/*.html' --public-url $(node public-url.js)",
    "watch": "eleventy --watch",
    "serve": "parcel src/home/index.html '_site/*.html' _site/*/index.html '_site/*/*/*.html'",
    "start": "run-p watch serve",
    "debug": "DEBUG=* eleventy",
    "lint": "prettier --write 'generate-api-docs/*.js' 'src/**/*.{js,json,md,scss}'",
    "generate-api-docs": "node generate-api-docs/ ../ ./api",
    "generate-api-docs:watch": "nodemon -w ../parcel -w generate-api-docs -x yarn generate-api-docs"
  },
  "devDependencies": {
    "@11ty/eleventy": "^1.0.2",
    "@11ty/eleventy-navigation": "^0.3.5",
    "@11ty/eleventy-plugin-rss": "^1.2.0",
    "@11ty/eleventy-plugin-syntaxhighlight": "^4.1.0",
    "@babel/generator": "^7.20.1",
    "@babel/parser": "^7.20.1",
    "@babel/traverse": "^7.20.1",
    "@parcel/packager-xml": "^2.15.0",
    "@parcel/transformer-js": "^2.15.0",
    "@parcel/transformer-react-refresh-wrap": "^2.15.0",
    "@parcel/transformer-sass": "^2.15.0",
    "@parcel/transformer-xml": "^2.15.0",
    "eleventy-plugin-toc": "^1.1.0",
    "flow-bin": "^0.177.0",
    "husky": "^4.3.6",
    "lint-staged": "^10.5.3",
    "markdown-it": "^12.0.4",
    "markdown-it-anchor": "^8.0.1",
    "nodemon": "^2.0.6",
    "npm-run-all": "^4.1.5",
    "nullthrows": "^1.1.1",
    "parcel": "^2.15.0",
    "postcss": "^8.3.6",
    "posthtml-include": "^1.7.0",
    "posthtml-prism": "^1.0.4",
    "prettier": "2.7.1",
    "process": "^0.11.10",
    "sass": "^1.55.0",
    "sharp": "^0.33.5",
    "tailwindcss": "^3.2.1",
    "tailwindcss-safe-area": "^0.2.2"
  },
  "dependencies": {
    "@alpinejs/intersect": "^3.10.5",
    "alpinejs": "^3.10.5",
    "focus-visible": "^5.2.0",
    "marked": "^2.0.7",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-use": "^17.3.1"
  },
  "resolutions": {
    "gulp-sass": "5.0.0",
    "sass": "1.55.0"
  },
  "lint-staged": {
    "*.{md,scss,js,json}": "prettier --write"
  },
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "alias": {
    "./assets/**": "./src/assets/$1",
    "./plugin-browser/**": "./src/plugin-browser/$1"
  },
  "@parcel/transformer-css": {
    "pseudoClasses": {
      "focusVisible": "focus-visible"
    }
  }
}

---

## File: vercel.json

{
	"version": 2,
	"alias": ["parceljs.org"]
}

---

## File: .yarnrc.yml

nodeLinker: node-modules

yarnPath: .yarn/releases/yarn-3.2.4.cjs

---

## File: packages/parcel-namer-website/package.json

{
  "name": "parcel-namer-website",
  "version": "1.0.0",
  "main": "WebsiteNamer.js",
  "engines": {
    "parcel": "^2.0.0-beta.1"
  },
  "dependencies": {
    "@parcel/plugin": "^2.15.0"
  }
}

---

## File: packages/parcel-resolver-website/package.json

{
  "name": "parcel-resolver-website",
  "version": "1.0.0",
  "main": "WebsiteResolver.js",
  "engines": {
    "parcel": "^2.0.0-beta.1"
  },
  "dependencies": {
    "@parcel/plugin": "^2.15.0"
  }
}

---

## File: src/src.json

{
  "tagOrder": [
    "Getting Started",
    "Migration",
    "Features",
    "Recipes",
    "Languages",
    "Plugin System"
  ]
}

---

## File: src/blog/blog.json

{
  "tags": "Blog"
}

---

## File: src/blog/alpha1/alpha1.md

---
layout: layout.njk
eleventyNavigation:
  key: blog-alpha-1
  title: Parcel 2 alpha 1 is here!
date: 2019-09-13
summary: 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.

- **🎛 Extensibility** — Parcel 2 is fully extensible, from end to end. The plugin types have been expanded to allow extending and overriding nearly all of the core behavior with easy to configure pipelines. While the default settings include everything in Parcel 1 (and more), now **you can customize and extend just about everything** if you need to.

- **⚖️ Scalability** — While Parcel has always utilized parallelism and caching to scale to large applications, this is taken even further in Parcel 2. We now **cache and parallelize even more** of Parcel’s work, so you can expect even faster builds, especially cached builds. We also keep much less in memory, so Parcel 2 can scale to even larger apps.

- **💪 Reliability** — Parcel 2 improves the reliability of our cache while at the same time improving performance to the max. We utilize a brand new cross platform filesystem [watcher](https://github.com/parcel-bundler/watcher), which can detect granular file changes even while Parcel is not running. At the same time, our asset graph can be invalidated super granularly, which means that **cached builds have almost exactly the same performance as watch mode!**

### Configuration

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.

- **🔎 Resolvers** — resolvers turn imports like import './foo' or import 'react' into full file paths like /my/project/foo.js. The default resolver in Parcel 2 includes support for the node resolution algorithm, plus some extras like aliases. But, if you want to extend or override the resolution algorithm for your project, now you can with a resolver plugin.

- **🦋 Transformers** — transformers compile code and other assets from one language to another, or just transform files in some way. For example, the TypeScript transformer compiles TypeScript to JavaScript, and the Babel transformer transpiles JavaScript to different JavaScript. Transformers are also responsible for extracting dependencies from code, such as import statements and require calls, which get passed back to the resolver, to another transformer, and so on until a full asset graph for the application is built.

- **🗃 Bundlers** — bundler plugins take an asset graph as input, and output a bundle graph which is like the asset graph but with the assets grouped into bundles. The default bundler groups assets with like file types like JavaScript and CSS together, and performs code splitting and some additional optimizations. I’m excited to see how the community will experiment with custom bundler plugins that take advanced code splitting even further!

- **🏷 Namers** — namer plugins are responsible for determining the output filenames for each bundle. The default namer plugin includes content hashing for long term cachability of assets, and the same naming rules as Parcel 1. If you need to customize the filenames of your bundles for any purpose, a namer plugin is the way to do it!

- **👟 Runtimes** — runtime plugins allow inserting code into bundles at build time. By default, we use this to add the runtime code needed to load bundles asynchronously, and insert the hot module replacement runtime for development, but you could use them to insert any kind of code you need conditionally at build time.

- **📦 Packagers** — packagers combine assets of a common type into an output bundle that can be loaded in a browser. For example, the JS packager combines JavaScript files together so that they are executed in the right order, at the right time.

- 🗜 **Optimizers** — optimizer plugins optimize a bundle in some way, for example minimizing or compressing files. For example, the [terser](https://github.com/terser-js/terser) optimizer minimizes JavaScript bundles.

- **✅ Validators** — validator plugins run in the background to perform code validation, such as linting (e.g. eslint) or type checking (e.g. TypeScript). They don’t block development builds, but when enabled, will block production builds from succeeding. Since they run in the background on a low priority queue, they don’t cause any performance degradation when you just want to make changes quickly.

- **🗞 Reporters** — reporter plugins receive events throughout the bundling process with status information and logging events. For example, the Parcel 2 CLI is implemented with a reporter, as is the dev server. You could also use reporters to implement other types of UIs or dashboards, bundle visualizers, etc.

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](https://dart.dev) to your app once you’ve published the parcel-transform-dart package.

    {
      "extends": ["[@parcel/config-default](http://twitter.com/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)._

The worker farm has been updated to make use of the new [worker_threads](https://nodejs.org/api/worker_threads.html) 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 `<script>` or `<style>` tag in an HTML file, a multi-part Vue SFC, or other types of multi-part files yet to be invented. These inline assets will be processed the same way separate files would, and can be re-inserted back into the file they came from after they are processed by their respective pipelines.

This kind of flexibility and composability has never been possible before in a JavaScript bundler, and I’m super excited to see what types of new tools built on top of Parcel this enables!

### The Team

Parcel 2 would not have happened without the amazing core team that has been working tirelessly to build it!

- [Will Binns-Smith](https://twitter.com/wbinnssmith)

- [Jasper De Moor](https://twitter.com/JasperDeMoor)

- [Devon Govett](https://twitter.com/devongovett)

- [Jamie Kyle](http://jamie.build)

- [Niklas Mischkulnig](https://twitter.com/mischnic)

- [Maia Teegarden](https://twitter.com/padmaia)

- [Kyle Welch](https://twitter.com/kylewelch)

Thanks to [Atlassian](https://www.atlassian.com) for investing so much into Parcel, and sponsoring two of the devs listed above full time (Maia and Will). And many thanks to everyone who has donated to our [Open Collective](https://opencollective.com/parcel) as well — it really helps make Parcel possible. 😍

### Try it out and help us get to the finish line!

You can install Parcel 2 with yarn add parcel@v2 to try it out. A [getting started guide](https://github.com/parcel-bundler/parcel/tree/v2#getting-started) is available in the readme. The CLI is mostly compatible with Parcel 1, but there are some differences you may come across in this early version. Also note that any Parcel 1 plugins you were using will no longer work in Parcel 2, and will need to be ported.

This is the first alpha of Parcel 2, and as it is alpha, there will be bugs and missing features. In particular, many of the plugins haven’t been ported from Parcel 1 to Parcel 2 yet. If you’d like to help, please feel free to check out the existing plugins on the [v2 branch](https://github.com/parcel-bundler/parcel/tree/v2/packages) for inspiration (we’ll have full docs by Parcel 2’s final release), and the [Parcel 2 label](https://github.com/parcel-bundler/parcel/issues?q=is%3Aissue+is%3Aopen+label%3A%22✨+Parcel+2%22) on GitHub. Some of the issues there are labeled with “Good First Issue” as well, and would be a good place to start.

Please [report any bugs](https://github.com/parcel-bundler/parcel/issues) you find on GitHub. You can also find me [@devongovett](https://twitter.com/devongovett) on Twitter.

- [GitHub](https://github.com/parcel-bundler/parcel)

- [Spectrum Community](https://spectrum.chat/parcel)

- [Support us on Open Collective](https://opencollective.com/parcel)

---

## File: src/blog/beta1/beta1.md

---
layout: layout.njk
eleventyNavigation:
  key: blog-beta-1
  title: Parcel 2 beta 1
date: 2020-06-19
summary: 📦 Parcel 2 beta 1 - improved stability, tree shaking, source map performance, and more! 🚀
---

The Parcel team is super excited to release the first beta of Parcel 2 today! This marks the first Parcel 2 release that’s more stable than our nightly and alpha releases, and our commitment to avoid changing most user facing APIs. Please try it out and give us your feedback on GitHub!



It’s been a while since our last alpha release, and there has been a ton of active development on Parcel 2 in the meantime. We’ve been focusing on **stability**, **performance**, and **reliability** as we prepare for our stable v2 release, but we’ve managed to sneak in a few new features too!

- **🌳 Improved tree shaking** — Parcel’s tree shaking implementation has improved tremendously since the last alpha release. In addition to a ton of bug fixes and performance improvements, Parcel 2 now produces source maps for tree shaken bundles, and displays friendly error messages when you reference an unknown symbol.

- **🗺 Faster source map generation**— Parcel now has a brand new [source map module](https://github.com/parcel-bundler/source-map), hand tuned for our specific usecases. It’s written in C++ for performance, and is **~20x faster** at combining source maps from multiple files!

- **#️⃣ Improved content hashing**— Parcel now has more reliable content hashing support for long term cacheability of bundles. In addition, Parcel 2 now avoids cascading invalidation by only updating a manifest in entry bundles rather than all referencing bundles.

- **🚨 Resolver diagnostics**— Parcel 2 now supports friendly error messages when it cannot find a module you’ve referenced in your code. These include a detailed code frame showing where the error occurred, along with suggestions on how you might be able to fix the issue.

- **📊 More accurate bundle reports**— The bundle reports that Parcel generates in your CLI at the end of a production build are now more accurate. They are now based on source maps, and exclude code that has been removed during tree shaking and minification for more accurate file sizes.

- **🐞 Tons of bugfixes and improvements** — This release includes countless bugfixes and stability improvements. The team has been working hard on testing Parcel 2 against some very large applications, and we’re excited to see how it works for you.

## Tree shaking

Building a production JavaScript compiler is extraordinarily challenging. We’ve been working on Parcel’s tree shaking implementation [since 2018](https://medium.com/@devongovett/parcel-v1-9-0-tree-shaking-2x-faster-watcher-and-more-87f2e1a70f79), and it has improved tremendously since then. Parcel 2 enables tree shaking by default, and we’ve recently been using it to deploy some very large applications in production at Atlassian and Adobe.

Parcel’s tree shaking implementation is unique among bundlers. Aside from supporting ES modules as many other tools do, Parcel also supports tree shaking CommonJS natively. While some libraries are now offering ES modules, most of the code on npm is still written in or transpiled to CommonJS before it is published. CommonJS can be difficult to statically analyze, like much of JavaScript, and we’ve put a huge amount of effort into making this transparent. We can statically analyze in a majority of cases, and automatically bail out and wrap the module in a function when it performs unsafe operations. We’ve discovered and fixed many bugs and edge cases in our tree shaking implementation over the last few months, and tested it extensively. We’d love to hear how it works on your application! Please [report any bugs](https://github.com/parcel-bundler/parcel/issues) you find.

Parcel now generates source maps for tree shaken bundles as well. This was a limitation since the initial tree shaking release, and a major challenge for us. Since tree shaking does not simply concatenate files together linearly, it was difficult to combine source maps in the correct way. Instead, we now store ASTs in our cache, and combine them together instead. This preserves location information as part of the AST nodes, which can be used to generate a final source map at the end as part of code generation.

In addition to source maps, location information also allows us to give more accurate error messages. We are now able to show detailed code frames for errors such as importing a non-existent export from a module and more.



HUGE thanks to [Niklas Mischkulnig](https://twitter.com/mischnic) for all of his work on improving the tree shaking compiler in Parcel. 🙏

## Source maps

Source maps can be quite CPU and memory intensive to generate, especially when combining source maps from many files. We previously used the Mozilla [source-map](https://github.com/mozilla/source-map) library to do this, but ran into performance issues on large bundles.

To address this, we’ve implemented [our own library](https://github.com/parcel-bundler/source-map) for combining and manipulating source maps. It’s a native node module, written in C++, that’s purpose-built for Parcel’s use cases. It utilizes [FlatBuffers](https://google.github.io/flatbuffers/) for serialization between workers and to the cache, which dramatically reduces the cost of generating and parsing that we had previously seen with JSON. Overall, it’s **~20x faster** than the JavaScript implementation at combining source maps together. As an example, a bundle that previously took 3 seconds to generate the source map now takes just 175ms!

In addition to the native node module, there’s also a Web Assembly build of the same library, which allows it to be used in environments like web browsers. While not as fast as the native bindings, it’s exciting that the same code can be reused rather than needing to maintain a pure JS implementation as well.

Thanks to [Jasper De Moor](https://twitter.com/JasperDeMoor) for all of his amazing work on source maps in Parcel! 🥳

## Content hashing

We have supported long term caching in Parcel via content hashed file names since [v1.7.0](https://medium.com/@devongovett/parcel-v1-7-0-9aac0c505837). These content hashes have historically been generated by hashing each individual file contained within the bundle. This ensured that changes to any file in the bundle caused the file name to update, and invalidate browser and CDN caches. However, it did not take into account cases where Parcel runtime code itself changed, rather than source code. This could happen when upgrading the version of Parcel, or a plugin that ran later (e.g. a minifier).

Parcel now generates hashes based on the final content of the bundle, after all packaging and minification has been done. This means that even if runtime code injected by Parcel changes, or your minifier changes the way it compiles your code, the content hashes will now update properly.

This was a challenge to implement, because bundles may reference other bundles as part of the code. Since the final names won’t be known until after the code has been generated, Parcel now inserts placeholder references into the content of the bundle, rather than the final bundle names. At the end, these are replaced with the final names as they are being written to disk.

In addition to more reliable content hashing, Parcel now avoids the [cascading invalidation](https://philipwalton.com/articles/cascading-cache-invalidation/) problem in many cases. This issue is well covered in the blog post linked above, but essentially since bundles may reference other bundles by content hashed file names, when a leaf bundle updates, all of the bundles leading to that bundle must also update in order to bust the cache. This leads to sub-optimal cache performance.

Instead of directly referencing bundles by full content hashed name, Parcel now includes a manifest in each entry bundle. This manifest includes a mapping of stable bundle ids to final content hashed filenames. Rather than referencing other bundles directly, only the bundle id is included. When a bundle further down the tree updates, invalidation no longer needs to cascade to intermediary bundles because the bundle id is stable. Only the entry bundle (containing the manifest) and the bundle that changed need to update. This can improve the cache hit rate significantly.

Thanks to [Maia Teegarden](https://twitter.com/padmaia) and [Will Binns-Smith](https://twitter.com/wbinnssmith) for their work on content hashing in Parcel 2!

## Resolver diagnostics

Parcel now includes improved error reporting when it cannot find a module you’ve referenced. This includes a code frame stack showing you exactly where the error occurred, and any intermediary files that led to the issue.

For example, the below screenshot shows an error that would typically only include the first line (Failed to resolve ‘invalid-entries’ from ‘./src/index.js’) and possibly the first code frame if you’re lucky. However, this doesn’t tell you where the error actually occurred. In this case, the invalid-entries module does exist, but it points to a non-existent file in its package.json. Parcel now displays a second code frame for the package.json, pointing to the exact line that caused the underlying issue.



## Upgrading

Upgrading from the previous alpha release of Parcel 2 should be fairly straightforward, but there are a few things to be aware of.

- **Config resolution changes** — Parcel now only supports a single .parcelrc config file in the root of your repository. Additional config files in sub-directories are no longer supported for performance reasons.

- **Config changes**— `transforms` has been renamed to `transformers` in .parcelrc for consistency with other plugins.

- **Target resolution changes** — Targets defined in package.json files within a monorepo are now resolved from the project root rather than individual packages when pointing to a file rather than the package directory itself. This means that you can point to files across multiple packages to build a single target, or point at the packages themselves to build the targets defined in each package. See the description [here](https://github.com/parcel-bundler/parcel/pull/4098) and [here](https://github.com/parcel-bundler/parcel/pull/4718) for more info.

- **Dist directory changes** — by default, Parcel now outputs into the dist directory in your project root in servemode, rather than a hidden directory inside the cache. This allows you to more easily inspect the built files during development. You can override this using the `--dist-dir` CLI option.

- **Plugin API changes** — there have been several plugin API changes. Please see the documentation, linked below, for more details.

## Documentation

We’ve been working on a [new documentation website](/) for Parcel 2! It’s still very much a work in progress, but we plan to cover everything from getting started with building a basic application or library with Parcel, to more advanced features, recipes, and building your own plugins. Please check it out and give us your feedback!

## Stability

As mentioned earlier, this is the first beta release of Parcel 2. This means it is more stable than a nightly or alpha release, but some changes are still expected before the fully stable release. In particular, beta means we are not planning on changing most user facing APIs such as configuration formats (in package.json and .parcelrc) and CLI arguments. Some changes are still expected to plugin APIs before the first release candidate, however we do not expect major changes at this point.

## Try it out!

If you’ve been waiting to try out Parcel 2, now would be a great time! You can install it by running yarn add parcel@next. If you need assistance, you can ask questions on [GitHub discussions](https://github.com/parcel-bundler/parcel/discussions), and if you run into bugs, please report them on [GitHub issues](https://github.com/parcel-bundler/parcel/issues). You can also find me [@devongovett](https://twitter.com/devongovett) on Twitter. We’re really excited to hear your feedback!

- [GitHub](https://github.com/parcel-bundler/parcel)

- [Support us on Open Collective](https://opencollective.com/parcel)

---

## File: src/blog/beta3/beta3.md

---
layout: layout.njk
eleventyNavigation:
  key: blog-beta-3
  title: Parcel 2 beta 3
date: 2021-05-18
---

The Parcel team is excited to release Parcel 2 beta 3! **This release includes a ground up rewrite of our JavaScript compiler in Rust, which improves overall build performance by up to 10x.** In addition, this post will cover some other improvements we’ve made to Parcel since our last update, along with our roadmap to a stable Parcel 2 release.

## 10x faster JavaScript compiler written in Rust 🚀

Over the past few months, we’ve been working on rewriting our JavaScript compiler in Rust! Parcel's JavaScript compiler is responsible for detecting dependencies in your code (like `import` statements and `new Worker()` calls), inlining `process.env` variables and other Node globals, and performing scope hoisting.

In addition, Parcel automatically transpiles your source code for your configured `browserslist` targets, along with non-standard syntax like JSX and TypeScript, and development features like React Fast Refresh.

Previously, all of this was implemented in JavaScript on top of a Babel AST. While we had [made](https://github.com/parcel-bundler/parcel/pull/4366) [great](https://github.com/parcel-bundler/parcel/pull/4815) [progress](https://github.com/parcel-bundler/parcel/pull/5432) optimizing this, JavaScript compilation was still by far the slowest part of Parcel. In particular, serializing large JavaScript ASTs to send between threads was very slow, and these large objects put a lot of pressure on the JavaScript garbage collector. Also, JavaScript code must be compiled by the engine every time it is run, which means it is slow to start up. While improving algorithmic complexity will result in performance improvements regardless of the language, that can only take you so far.



Parcel's new JavaScript transformer is written in Rust on top of the [SWC](https://swc.rs) compiler. SWC provides JavaScript parsing and code generation, along with a solid foundation for building super fast AST transformations. Rust provides predictable performance, instant startup times, and the ability to optimize down to the hardware level.

In addition, the scope hoisting linker now operates only on strings rather than ASTs, which also massively improves performance because we avoid serializing and deserializing these large objects. This also allows code generation to be parallelized across all files rather than performed on the whole bundle at once.

**Overall, this improves build performance by up to 10x!**

On the ESBuild benchmark, Parcel is now ~10x faster without Terser, and ~3x faster when minification is enabled.



### Transpilation performance

In addition, SWC replaces Babel by default for transpilation when a `browserslist` is set, as well as for compiling JSX and TypeScript, and React Fast Refresh. **SWC is 20x faster** than Babel, so this change should also improve overall performance significantly.

While SWC is the default, rest assured that **Babel is still supported** as well. If you have a custom Babel configuration in your project, it will still be used automatically. This means that custom Babel plugins (e.g. CSS-in-JS transforms, Babel macros, etc.) continue to work out of the box. Scope hoisting, dependency collection, and everything else that was built into Parcel before will now occur in Rust, but this should be completely transparent.

This does open up the possibility to improve the performance of your build even further, however. You can now remove `@babel/preset-env`, `@babel/preset-react`, and `@babel/preset-typescript` from your `.babelrc` and they will be automatically handled by SWC instead. This can significantly improve your build performance. If you have additional custom Babel plugins, you can leave them in your Babel config. If not, you can delete your Babel config entirely. We will likely add a warning in the future to assist with this migration.

### Scope hoisting improvements

Aside from performance, we ran into some issues with our old scope hoisting implementation that motivated a rewrite. In particular, several JavaScript bundlers including Parcel have [bugs](https://github.com/parcel-bundler/parcel/issues/5659) related to execution ordering when scope hoisting and code splitting are used together.

Scope hoisting is the process of combining multiple JavaScript modules together into a single scope. This enables dead code elimination (aka tree shaking) to be more effective, and improves runtime performance by making cross-module references static rather than dynamic property lookups.

When hoisting multiple modules together into the same scope rather than wrapping each module in a separate function, it becomes difficult to ensure that these modules always execute in the correct order when they are referenced across bundles.

In addition, sometimes small modules are duplicated between multiple bundles in order to avoid producing many very tiny output files and increasing the number of HTTP requests needed to load a page. Previously, this could result in a module executing more than once, which could break many things, including side effects (e.g. mutating the DOM) and singleton patterns.

In order to fix these problems, it was necessary to rethink how our scope hoisting compiler worked from the ground up. The result is a hybrid between scope hoisting where we can, but falling back wrapping modules in a CJS-style function with a global module registry where needed. This ensures that modules that are referenced between bundles execute in the correct order, and that duplicated modules only execute once.

If you’re curious to read more about how our scope hoisting implementation works, check out the [design document](https://github.com/parcel-bundler/parcel/blob/v2/packages/transformers/js/hoist.md), which goes into detail on all of these topics.

## Tree shaking dynamic import

Another feature related to our scope hoisting implementation is support for tree shaking dynamic `import()`. Parcel can detect which properties of a dynamic import are accessed, and exclude the exports from the resolved module that aren't used. This works with promise chaining, async/await, destructuring, and static object property accesses. If anything is accessed non-statically, e.g. a computed property, then all of the exports will be included.



## Tree shaking CSS modules

We also now have support for tree shaking CSS modules. When you import a CSS module in JavaScript, Parcel tracks which classes are used, and automatically excludes the unused selectors from the compiled CSS file. In addition, class names are now automatically inlined in the compiled JavaScript rather than stored in a large object map. This should help reduce the bundle size of both CSS and JS output!



## Lazy development builds

In development, it can be frustrating to wait for your entire app to build before the dev server starts up. This is especially true when working on large apps with many pages. If you’re only working on one feature, why do you need to wait for all of the others to build unless you actually navigate to them?

Parcel now supports a `--lazy` CLI flag when using the dev server. When enabled, Parcel only builds files that are requested on demand, which can significantly reduce development build times. The server starts instantly, and when you navigate to a page for the first time, Parcel builds only the files necessary for that page. When you navigate to another page, that page will be built on demand.  If you navigate back to a page that was previously built, it loads instantly.

<video src="lazy.mp4" playsinline loop autoplay muted></video>

This also works with dynamic `import()`, not just completely separate pages. So if you have a page with a dynamically loaded feature, that feature will not be built until it is activated. Parcel is smart enough to eagerly build all of the dependencies of the requested file at once, without waiting for them to be requested as well. If you have some CSS that goes along with your JavaScript, or some referenced images, they'll all be built together – no network waterfall!

The tradeoff, of course, is that page loads and dynamic imports can be slightly slower the first time they are loaded. But with Parcel's disk caching, that should only ever happen once. Even when you restart Parcel, there should be no need to rebuild files that didn't change.

## Cache reliability

Speaking of caching, another area that we’ve been working on is cache reliability. We want users to trust the cache, so we need to ensure that everything that could possibly invalidate the cache actually does invalidate the cache. This is much harder than it sounds. Modern JavaScript build tools have a lot of inputs to keep track of – files on disk, configuration, environment variables, the dev dependencies that were used to compile your code, and much more. When any of these change, Parcel needs to invalidate the cache and re-compute the output.

Parcel tracks all of these inputs in a graph. [Our file watcher](https://github.com/parcel-bundler/watcher) watches for changes on disk, and invalidates any requests that are connected to the files that changed. This also occurs when you restart Parcel. Our watcher integrates with operating system level APIs to quickly determine what files changed since you last ran Parcel, which means that restarting Parcel is almost as fast as using watch mode!

## Dev dependency HMR

A side benefit of all of this work on cache invalidation is that watch mode also benefits. One cool feature that we’ve implemented is **HMR for Parcel plugins** and other build dependencies. When you make a change to a plugin's source code, we reload the plugin in place and rebuild any files that it had previously compiled. This makes it super fast to work on a plugin and see your changes instantly – no need to restart Parcel.

<video src="plugin-hmr.mp4" playsinline loop autoplay muted></video>

It also works with Babel plugins, PostCSS plugins, and any other dev dependency involved in your build. You can even edit plugins in `node_modules` and Parcel will recompile automatically. This is useful when you need to debug something in your build pipeline, or make use of tools like [patch-package](https://github.com/ds300/patch-package).

## Fewer dependencies

Parcel supports many different languages and tools out of the box, which makes it really easy to get started. But one downside of this is that installing Parcel includes many dependencies that you might not use. This not only uses up disk space and network bandwidth, but is also more dependencies for you to maintain and audit.

We wanted to reduce Parcel's dependencies while still keeping things really simple to use. To do this, we now only install essential plugins by default, and auto install additional plugins into your project on demand.

<video src="autoinstall.mp4" playsinline loop autoplay muted></video>

By default, we include support for standard web languages like HTML, CSS, and JavaScript. But as soon as you include a SASS file, Vue, Elm, CoffeeScript, or any other file type that Parcel recognizes, we’ll automatically install the necessary plugins and all peer dependencies into your project. This keeps Parcel super easy to use (zero config) but also reduces the number of dependencies in your project.

## Roadmap

Parcel 2 has been in development for a couple years now, and we haven’t always done the best job of updating the community on where things stand on our roadmap to a stable release. So, this section is an update on our progress.

Beta 3 will most likely be the final beta before our first release candidate, which we're hoping will be out in about a month. For the first rc, we are working on the following items:

- Improved cache invalidation for packaging and optimizing
- Ensuring the cache is portable between machines or different file paths (e.g. in CI)
- Improved automatic differential bundling support (module/nomodule)
- API consistency

After rc, the public API will be frozen, and we’ll focus on bug fixes and documentation. This will hopefully take around a month. Once ready, we’ll release 2.0!

At this point, it is very likely that the plugin APIs for bundlers, runtimes, and validators will be marked as experimental in Parcel 2.0. This means these features will not follow semver and we will continue iterating on them after the initial stable Parcel 2 release. In addition, we have many other features and improvements planned for post-2.0, including further performance optimizations.

## Thanks!

As always, thanks for trying out our betas and giving us feedback on [GitHub](https://github.com/parcel-bundler/parcel/issues). You can also donate to our [open collective](https://opencollective.com/parcel), which helps support our contributors.

---

## File: src/blog/parcel-css/parcel-css.md

---
layout: layout.njk
title: 'Announcing Parcel CSS: A new CSS parser, compiler, and minifier written in Rust!'
eleventyNavigation:
  key: blog-parcel-css
  title: Announcing Parcel CSS
date: 2022-01-12
---

I'm very excited to announce [@parcel/css](https://github.com/parcel-bundler/parcel-css), a new CSS parser, compiler, and minifier written in Rust! Check it out [on GitHub](https://github.com/parcel-bundler/parcel-css), or try a [live demo](https://parcel-css.vercel.app) right in your browser.

Parcel CSS has significantly better performance than existing tools, while also improving minification quality. In addition to minification, Parcel CSS handles compiling CSS modules, tree shaking, automatically adding and removing vendor prefixes for your browser targets, and transpiling modern CSS features like nesting, logical properties, level 4 color syntax, and much more.

It can be used with Parcel, as a standalone library from JavaScript or Rust, or wrapped as a plugin within any other tool. The Rust library is designed as a platform for CSS tooling, with access to fully parsed data structures for all CSS rules, selectors, properties, and values.

## Performance

Parcel CSS is extremely fast. It is over 100x faster than CSSNano for minification, and over 3x faster than ESBuild. It can minify over 2.7 million lines of code per second on a single thread. This example shows a benchmark that minifies Bootstrap 4, which is about 10,000 lines.

{% include "./performance.svg" %}

Even though it is extremely fast, Parcel CSS does not compromise on size. It can produce much smaller output than other tools in many cases thanks to the ability to convert legacy CSS syntax used in many libraries to smaller modern syntax, as well as its full understanding of every individual CSS property.

{% include "./size.svg" %}

Parcel CSS is fast not only because it is written in a native language, but because it was designed from the start with performance in mind. It is designed to be efficient in the way it uses memory, including optimizations such as representing vendor prefixes using single byte bit flags, and parsing all CSS properties into structured data rather than representing them as strings that need to be re-parsed each time they are used.

## Architecture

Parcel CSS is based on the [cssparser](https://github.com/servo/rust-cssparser) Rust crate, a browser-grade CSS tokenizer created by Mozilla and used in Firefox. This provides a solid foundation, including tokenization and basic parsing. However, it does not interpret any CSS properties or at rules. That's where Parcel CSS comes in. It handles parsing each individual rule and property value, as well as minification, compilation, and printing back to CSS.

Many other CSS processors treat property values as strings, or an untyped series of tokens. This means that each transformer that wants to do something with these values must parse and interpret them itself, leading to duplicate work and inconsistencies. For example, the AST for a CSS property parsed by PostCSS looks like this:

```json
{
  "type": "decl",
  "prop": "background",
  "value": "url(img.png) 20px 10px / 50px 100px"
}
```

Even if you use `postcss-value-parser`, a separate library used by many PostCSS plugins to tokenize property values, the meaning of each token is still not interpreted. The above value parses like this:

```javascript
[
  {
    type: 'function',
    value: 'url',
    nodes: [ { type: 'word', value: 'img.png' } ]
  },
  { type: 'space', value: ' ' },
  { type: 'word', value: '20px' },
  { type: 'space', value: ' ' },
  { type: 'word', value: '10px' },
  { type: 'div', value: '/' },
  { type: 'word', value: '50px' },
  { type: 'space', value: ' ' },
  { type: 'word', value: '100px' }
]
```

While a bit more structured and easier to deal with than a string, it's not clear that `20px` is the value for `background-position-x` and `50px` is the value for the background width. This must be interpreted by the user.

Parcel CSS parses all values using the grammar from the CSS specification, and exposes a specific value type for each property. For example, Parcel CSS represents the above property like this:

```rust
Background([Background {
  image: Url(Url { url: "img.png" }),
  color: CssColor(RGBA(RGBA { red: 0, green: 0, blue: 0, alpha: 0 })),
  position: Position {
    x: Length(Dimension(Px(20.0))),
    y: Length(Dimension(Px(10.0))),
  },
  repeat: BackgroundRepeat {
    x: Repeat,
    y: Repeat,
  },
  size: Explicit {
    width: LengthPercentage(Dimension(Px(50.0))),
    height: LengthPercentage(Dimension(Px(100.0))),
  },
  attachment: Scroll,
  origin: PaddingBox,
  clip: BorderBox,
}])
```

This is exactly how browsers parse CSS. Values are interpreted, and implicit default values like background attachment are filled in. This improves performance because every time a transformer wants to do something with a property, it doesn't need to re-parse it, transform, and stringify it again. This also improves reliability, because each transformer won't parse the value slightly differently, or take shortcuts like using regexes or string replacement, which can lead to bugs.

Since property values are individually interpreted, this approach also enables better minification. For example, implicit default values can be automatically removed, whitespace can be removed where not needed, longhand properties can be merged into shorthands when possible, etc.

This architecture provides a foundation for CSS tooling, which can focus on using properties in interesting ways rather than on parsing and interpreting them.

## Try it out

**If you're using Parcel**, you can try out Parcel CSS as your CSS transformer, minifier, or both. We hope to replace the default CSS transformer and minifier soon, but would like to get feedback first. For now, just add the following to your `.parcelrc` file:

```json
{
  "extends": "@parcel/config-default",
  "transformers": {
    "*.css": ["@parcel/transformer-css-experimental"]
  },
  "optimizers": {
    "*.css": ["@parcel/optimizer-css"]
  }
}
```

You should also add a `browserslist` property to your package.json, which defines the target browsers that your CSS will be compiled for.

While Parcel CSS handles the most commonly used PostCSS plugins like `autoprefixer`, `postcss-preset-env`, and CSS modules, you may still need PostCSS for more custom plugins like TailwindCSS. If that's the case, just add `@parcel/transformer-postcss` before `@parcel/transformer-css-experimental`, and your PostCSS config will be picked up automatically. You can remove the plugins listed above from your PostCSS config, and they'll be handled by Parcel CSS.

**If you are not using Parcel**, you can still try Parcel CSS. You can either use it standalone with the [JavaScript API](https://github.com/parcel-bundler/parcel-css#from-javascript), or create a plugin for your favorite build tool. We hope to see Parcel CSS adopted by many tools, not just Parcel, so we can move the entire CSS tooling ecosystem forward.

**You can also try out the [parcel_css](https://docs.rs/parcel_css) Rust crate**, which gives you full access to the parsed AST, and allows you to build custom tooling. More API docs are coming soon, but for now, you'll want to start with the [StyleSheet](https://docs.rs/parcel_css/1.0.0-alpha.10/parcel_css/stylesheet/struct.StyleSheet.html) API. Note that while the JavaScript API is stable, the Rust API is still alpha and structures may change between versions as we continue improving Parcel CSS.

Please let us know how it goes! You can file issues for bugs or feature requests on [GitHub](https://github.com/parcel-bundler/parcel-css).

---

## File: src/blog/rc0/rc0.md

---
layout: layout.njk
eleventyNavigation:
  key: blog-rc-0
  title: Parcel 2 RC
date: 2021-08-03
---

The Parcel team is very excited to announce the first Parcel 2 release candidate! This release includes many improvements, including new features, better performance, API consistency, and lots of bug fixes and stability improvements.

## Automatic differential bundling via native ES modules

Parcel 2 now automatically generates both native ES modules for modern browsers and fallback classic scripts for old browsers. This reduces bundle sizes significantly for a majority of users by shipping modern syntax rather than transpiling to ES5.

### Classic scripts vs. ES modules

One of Parcel’s fundamental design goals has always been to work like the web does. We try to avoid lock in by following web standards and not inventing Parcel-specific syntax or features as much as possible. One place where this was not true in Parcel v1 was the way Parcel handled `<script>` tags in HTML. Previously, Parcel would treat all scripts as modules, including support for `import` and `export` statements, and isolating each file's top-level scope from other modules. While convenient, this is not actually how the `<script>` tag works in the browser.

Classic scripts, without `type="module"`, actually treat variables in the top-level scope as globals, and cannot have imports or exports, so now Parcel matches this behavior as well. This also fixes some issues with legacy libraries like jQuery that expect to be running in a global script environment and not in an isolated module.

When you upgrade from a previous version of Parcel, you’ll need to add the `type="module"` attribute to your script tags. You'll see a diagnostic like the one below pointing you to the locations you need to modify.



### Differential bundling

Differential bundling is the idea of shipping multiple versions of your code for different targets, and allowing the browser to choose the most optimal one to download. Modern browsers support `<script type="module">`, which in addition to supporting import and export syntax, also supports other modern syntax such as classes, arrow functions, async/await, and more. Shipping modern syntax rather than transpiling this syntax to older JavaScript versions, [can dramatically reduce](https://web.dev/publish-modern-javascript/) bundle sizes and improve load times. However, if you still need to support older browsers, `<script nomodule>` can be used to send a transpiled version of your code that will only be loaded in older browsers. This gives you the best of both worlds – smaller bundles for a majority of users, but without sacrificing users on older browsers.

Differential bundling using the module/nomodule pattern is now completely automated in Parcel 2. Just use a `<script type="module">` tag in your HTML file, pointing to your source code, and Parcel will automatically generate a `nomodule` version as well if needed.

```html
<script type="module" src="app.js"></script>
```

becomes:

```html
<script type="module" src="app.c9a6fe.js"></script>
<script nomodule src="app.f7d631.js"></script>
```

This happens automatically based on your browser targets, as declared in the `"browserslist"` key in your package.json file. If some of your targets don't support ES modules natively, a `nomodule` version will be compiled automatically.

## Improved JSX support

Parcel has always supported JSX out of the box, and even automatically detects which library you're using (e.g. React, Preact, etc.) and compiles accordingly. New in this release, Parcel now supports the [new JSX runtime](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html) added in React 17. This is completely automatic – Parcel detects the version of React used by your code and chooses the correct JSX runtime accordingly. The new JSX runtime should result in smaller bundles, and performance improvements. You also no longer need to import React manually in every file in order to use JSX. Please read the [blog post](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html) from the React team for more information.

In addition, Parcel will now read the `tsconfig.json` or `jsconfig.json` file in your project, which allows you to configure several aspects of JSX compilation. You can use this to override the JSX runtime, library, and other properties, as well as enable other experimental JavaScript features like decorators. Please see the [TSConfig reference](https://www.typescriptlang.org/tsconfig) from the TypeScript team for more information.

## Improved worker support

Parcel has supported web workers and service workers for a long time, and in this release we’ve made some major improvements. Similar to `<script>` tags in HTML, there are actually two kinds of workers supported in browsers: classic script workers, and ES module workers. Parcel has historically considered all workers to be modules, but in this release, we now match native browser behavior and treat these differently.

To create a worker that uses ES module syntax such as `import` and `export`, the `type: 'module'` option is now required when constructing the worker. In addition, the `URL` constructor is now required to create a worker rather than passing a string literal. These changes improve Parcel's compatibility with both native browser behavior as well as other tools in the ecosystem.

```js
new Worker(
  new URL('worker.js', import.meta.url),
  {type: 'module'}
);
```

In addition, in module workers, `importScripts` is no longer supported, and should be replaced by an `import` statement or dynamic `import()`.

Parcel will display diagnostics to help you migrate existing code to the new patterns.



### Worklet support

In addition to web workers and service workers, Parcel also now supports worklets, including [CSS Houdini paint worklets](https://developers.google.com/web/updates/2018/01/paintapi) as well as [web audio worklets](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API/Using_AudioWorklet).

Paint worklets are detected automatically using the following syntax:

```js
CSS.paintWorklet.addModule(new URL('worklet.js', import.meta.url));
```

Web audio worklets are not statically analyzable, so for these you can use the `worklet:` named pipeline to get a URL to the worklet file compiled for the correct environment.

```js
import workletUrl from 'worklet:./worklet.js';

context.audioWorklet.addModule(workletUrl);
```

## Improved library builds

In this release, Parcel’s support for building libraries has been improved.

Parcel now supports the `.mjs` and `.cjs` file extensions used by Node.js to indicate whether a module is ESM or CommonJS. In addition, the `"type": "module"` field in package.json is supported. These hints help Parcel automatically determine which output format to use when compiling your source code. You'll also get a diagnostic if you try to use an unsupported file extension in package.json fields.



In addition, when you use workers or URL dependencies in your code, Parcel will now produce statically analyzable output when building a library. This enables your library to be bundled by Parcel or another bundler later when used in an app. URL dependencies compile to the `URL` constructor, which is supported both natively in Node and the browser as well as by many bundlers.

```js
new URL('some-code.js', import.meta.url)
```

Finally, we have improved our diagnostics for many cases related to libraries. For example, you’ll get a diagnostic when scope hoisting is disabled for library builds, or an unsupported output format is used. Another useful diagnostic we added lets you know when you have an external dependency in your code that is not declared in your package.json. This helps prevent shipping code that will break when your library is used by a downstream consumer.



## Miscellaneous JavaScript improvements

### Multiple dependency types in the same file

Previously, it was impossible to use multiple types of dependencies on the same specifier within a single file. For example, a file could not have both a static import and a dynamic import with the same specifier. This is now supported correctly.

```js
import something from './foo';

import('./foo');
```

### Destructuring process.env

Using destructuring syntax on process.env is now possible.

```js
let {NODE_ENV, API_TOKEN} = process.env;
```

### Support for standalone import.meta

Parcel now supports `import.meta` more fully. When referencing `import.meta` by itself, you'll now get an object containing a `url` property. `import.meta.url` compiles directly to the same URL, without the intermediary object. The URL is a `file://` URL containing a relative path from your project root to the file containing the `import.meta.url` reference.

```js
console.log(import.meta);
// => {url: 'file:///src/App.js'}

console.log(import.meta.url);
// => 'file:///src/App.js'
```

In addition, `import.meta.url` can be used as a self-reference when constructing a worker in cases where you want the file that starts the worker to also be the worker itself.

```js
new Worker(import.meta.url, {type: 'module'});
```

## Glob resolver plugin

Parcel 2 now has a glob resolver plugin that works similarly to the glob importing support in Parcel 1. This allows you to import multiple files at a time, and get back an object with keys corresponding to the files.

```js
import * as files from './files/*.js';

console.log(files.foo);
```

Is equivalent to:

```js
import * as foo from './files/foo.js';
import * as bar from './files/bar.js';

let files = {
  foo,
  bar
};
```

This also works with pipelines like `url:`, as well as with dynamic import.

```js
let files = import('./files/*.js');

async function doSomething() {
  let foo = await files.foo();
  let bar = await files.bar();
  return foo + bar;
}
```

Since glob imports are non-standard, they are not included in the default Parcel config. To enable them, add `@parcel/resolver-glob` to your `.parcelrc`.

```json
{
  "extends": "@parcel/config-default",
  "resolvers": ["@parcel/resolver-glob", "..."]
}
```

## Performance improvements

In our last release, we [announced](/blog/beta3/) our new JavaScript compiler written in Rust that improves performance by up to 10x. This release continues our work on improving performance, and is overall **~38% faster** than the previous beta. There have been many small changes that add up, but some of the highlights are described below.

### LMDB

Parcel caches everything it does on the file system. This improves performance when restarting Parcel by avoiding duplicate work. In addition, the file system is used during builds as a temporary storage area to communicate between worker threads. This also enables Parcel builds to be scalable to very large projects that exceed the amount of available memory. As such, the performance of writing and reading from the file system is very important to the overall performance of Parcel builds.

In this release, we’ve replaced the file system caching implementation with a store backed by [LMDB](https://symas.com/lmdb/). LMDB is an extremely fast embedded key-value store written in C. In particular, we're using the excellent [lmdb-store](https://github.com/DoctorEvidence/lmdb-store) module for Node. It uses a single memory-mapped file, and automatically handles writes in an asynchronous background thread.

**Using LMDB rather than the file system for our cache improves performance by ~20%!**

### xxHash

Parcel relies heavily on hashing for many things, including cache keys, content hashes, etc. We’ve relied on the builtin Node md5 function for most of our hashing previously, but in this release we’ve replaced this with [xxHash](http://cyan4973.github.io/xxHash/). xxHash is an extremely fast hash function, operating at RAM speed limits. We built a custom Node wrapper around a Rust implementation of xxHash which is ~7x faster than md5. Overall, this improves Parcel build performance by ~5%.

### Source maps improvements

Parcel uses [our own library](https://github.com/parcel-bundler/source-map), written in Rust, to manipulate source maps. Serializing and deserializing large source maps from the cache can take a significant amount of time. In this release, we replaced [Serde](https://serde.rs) and [Bincode](https://github.com/bincode-org/bincode) with [rkyv](https://github.com/rkyv/rkyv), an extremely fast zero copy deserialization framework for Rust. This is ~2.5x faster at reading a cached source map, which equates to ~5% faster overall Parcel builds.

## Caching improvements

Reliable caching has been a big area of focus in Parcel 2, as described in our previous blog posts. In this release, we’ve continued this work and completed the migration of all parts of Parcel 2 to our request-based caching architecture.

In particular, packaging and optimizing bundles was the last remaining phase of Parcel that was not fully reliable. We now properly invalidate the cache when configuration for packager and optimizer plugins change. In addition, only the bundles which have actually changed will be re-packaged and written to disk, which improves performance. If the dist directory is deleted or bundles are modified manually, Parcel will detect this and copy the previously packaged bundle from the cache back to the dist dir automatically.

Finally, the cache is now resilient to location and platform changes. For example, if your project is moved to a different location on the file system, or cloned on a different machine, the cache can now be reused. All referenced file paths are now stored relative to the project root rather than as absolute paths. They are also stored with platform-agnostic separators, which means caches can be shared between POSIX and Windows machines.

## API changes

In this release, we’ve made significant changes to our plugin API. If you have any existing plugins, you’ll likely need to update them. Since this is a release candidate, we’re committed to avoiding breaking API changes after this release.

The changes are mostly about improving consistency, readability, type safety, and understandability of the API. For example, the `loadConfig` API that is supported by all of our plugin types is now fully typed. In addition, the Asset and Bundle APIs have reduced their reliance on boolean flags and have replaced these with a smaller set of enumerations which indicate which options are actually mutually exclusive. There have been many changes, so please check out the API diff [here](https://github.com/parcel-bundler/parcel/compare/v2.0.0-beta.3.1...v2.0.0-rc.0#diff-8e7d238bb30ff1dc759768c799d9cd63024b9297af540bc3d2b10cddb9e159c9).

Finally, we now publish TypeScript definitions along with all of our public packages. This includes the plugin API as well as the programatic API for Parcel core. This should help both when writing plugins in TypeScript, as well as when using plain JavaScript in an editor like VSCode.

## Miscellaneous

This release includes a lot of other small improvements and bug fixes. A few highlights are below. See the [commit diff](https://github.com/parcel-bundler/parcel/compare/v2.0.0-beta.3.1...v2.0.0-rc.0) for a full list of changes, or the list of bugs fixed in the GitHub [milestone](https://github.com/parcel-bundler/parcel/milestone/9?closed=1).

### SVG optimizer

Parcel now includes an SVG optimizer plugin based on [SVGO](https://github.com/svg/svgo). This automatically reduces the file sizes of standalone `.svg` files referenced in your build. It can be configured with an `svgo.config.json` or `svgo.config.js` file.

In addition, SVGO is also used for embedded SVG inside HTML files. There have been several bug fixes related to that in this release as well.

### Image references

Parcel 2 no longer requires the `url:` prefix when referencing image files. These can be imported in JavaScript or referenced from HTML or CSS, and will result in a transformed URL that includes a content hash for long term caching.

Parcel also includes an image transformer, which you can enable by using a query parameter. This allows you to resize or convert images from a source file automatically. For example, in HTML you could reference the same image multiple times with different query params to generate multiple different representations in different formats.

```html
<picture>
  <source src="snow.jpg?as=webp&width=400" type="image/webp" />
  <source src="snow.jpg?as=jpg&width=400" type="image/jpeg" />
  <img src="snow.jpg?as=jpg&width=400" alt="snow" />
</picture>
```

### Web manifests

Parcel supports [web manifest](https://developer.mozilla.org/en-US/docs/Web/Manifest) files, which enable PWAs to be installed on the user's device. These are referenced from an HTML file using a `<link rel=“manifest”>` tag. Parcel automatically handles URL references in these files just like any other dependency. In this release, you can now use a `.json` file rather than a `.webmanifest` file, which many developers find preferable.

## Try it out!

Please try out the release candidate and give us feedback on [GitHub](https://github.com/parcel-bundler/parcel/issues). We will be fixing bugs, and improving the documentation over the next month or so before our stable release. You can also donate to our [open collective](https://opencollective.com/parcel), which helps support our contributors. Thanks!

---

## File: src/blog/v2/v2.md

---
layout: layout.njk
eleventyNavigation:
  key: blog-v2
  title: Announcing Parcel v2!
date: 2021-10-13
---

The Parcel team is beyond excited to announce that v2.0.0 stable is now available! 🎉

**Parcel 2 brings the zero configuration experience you know and love from Parcel 1, and makes it scalable and extensible to projects of any size and complexity.** It is already being used in production at some of the biggest companies in the industry including Atlassian, Adobe, and Microsoft.

Check out our [new website](/) and documentation, and the repo on [GitHub](https://github.com/parcel-bundler/parcel)!

## What's new in Parcel 2?

Parcel 2 is a ground up rewrite of Parcel that has touched every aspect. If you haven’t followed along with our pre-release blog posts, here are a few highlights.

- 🔌 **An all new plugin system**, which makes Parcel fully extensible. This allows Parcel to scale from small side projects to massive production applications with complex build requirements.
- 🌳 **Tree shaking is enabled by default**, including support for ES modules, CommonJS, dynamic imports, and CSS modules.
- 🚀 **Massive performance improvements**, including a new JavaScript compiler written in Rust, and a more parallelized architecture that takes advantage of all of your CPU cores.
- 🖖 **Automatic differential bundling via native ES modules**, which enables you to ship much smaller bundles with modern JavaScript syntax for a majority of users, with automatic fallback for older browsers if needed.
- ✂️ **Automatic code splitting**, including deduplicating common modules into shared bundles that can be loaded and cached in parallel.
- 🖼 **Image resizing, conversion, and optimization**, including support for modern image formats like AVIF and WebP, and automatic lossless optimization for JPEGs and PNGs.
- 💵 **Dramatically improved cache reliability**, including portability across machines, and automatic tracking of all configs, plugins, dev dependencies, and more – no configuration needed!
- 🔥 **Improved hot reloading**, including support for React Fast Refresh.
- 🪆 **Support for bundle inlining**, which allows you to embed the compiled contents of a bundle inside another, for example inlining an image as a data URL.
- 📚 **Support for building libraries**, including output to ES modules, CommonJS, and even bundling TypeScript definitions.
- 🧘 **Lazy development mode**, which enables Parcel to build only the files that are requested by the browser, leading to improved dev server cold startup times.
- 👷 **Improved web worker support**, including support for native ES module workers, worklets, service worker manifests, and more.
- 🚨 **Better diagnostics**, with beautiful syntax highlighted code frames, hints, and even documentation links to learn more.
- 👀 **A more reliable file watcher**, written in C++ and integrated with low level operating system APIs for fast granular cache invalidations even across Parcel restarts.
- 🗺 **Faster and more accurate source maps** using Parcel's new source maps library, which is written in Rust for a 20x performance boost over Parcel 1.
- … and a ton more!

Check out the [migration guide](/getting-started/migration/) to learn how to upgrade an existing project from Parcel 1 to Parcel 2. For many projects, it's as simple as updating the dependency in your package.json!

If you’re starting a new project, we have getting started guides for [web apps](/getting-started/webapp/) and [libraries](/getting-started/library/), and full [documentation](/docs/) on all of Parcel’s features, including all of the languages and frameworks Parcel supports.

Finally, check out our [fancy new home page](/) to get an overview of all of the features in Parcel 2! 🥳

## Why Parcel?

These days, there are a lot of build tools available to choose from, so what makes Parcel 2 different?

**Parcel’s philosophy is to enable web development best practices out of the box with zero configuration, but allow you to override and extend every aspect to fit your needs.** Best practices like automatic code splitting optimized for HTTP2, content hashed file names for long term caching, differential bundling, tree shaking, image optimization, and more are all supported out of the box completely automatically. But if you need to tweak any of these to match your specific requirements, you have full control.

**Parcel is designed for the web, not just JavaScript.** Most Parcel projects start with an HTML file, and follow all of the dependencies in your whole application from there, just like a web browser. This includes JavaScript, CSS, SVG, images, fonts, videos, WebGL shaders, RSS feeds, and much more. Native web APIs like web workers, service workers, and URL references just work out of the box.

**Parcel can build multiple targets at once**, for example a library with an ES module, CommonJS, and TypeScript definitions, a modern and legacy build of an application, or a server and a client. All of these are built in parallel, and live update as you make changes.

**Parcel’s architecture is completely language agnostic**, not a JavaScript bundler with bolted on support for other file types. The plugin system has been designed to model every aspect of modern web development, from multi-step file transformation pipelines to bundling, optimizing, and compressing output files. Each plugin type has a specific, well defined API designed for its purpose with full documentation and TypeScript definitions. The plugin system is designed for performance, with automatic parallelization and caching.

## Who's using Parcel 2?

Though we’re only just releasing the stable version of Parcel 2 today, it has been available in pre-release for a while and many teams are already using it in production.

At **Adobe**, many products have been using Parcel since v1, and several of them are already using v2 in production. This includes the main [Experience Cloud](https://business.adobe.com) app, the [React Spectrum](https://github.com/adobe/react-spectrum) component library, [Adobe Launch](https://business.adobe.com/products/experience-platform/launch.html), [Adobe I/O App Builder](https://adobe.io/app-builder), and many more. Using Parcel 2 has resulted in reduced bundle sizes leading to improved loading performance, thanks to the new automatic code splitting and improved tree shaking.

**Atlassian** has been integral to the development of Parcel 2 from the beginning, and has invested a tremendous amount into the project. They helped design the initial architecture for v2, and currently fund a team of developers to contribute to it. This includes many contributions across Parcel, including the core bundling algorithm, caching architecture, and much more. [Bitbucket](https://bitbucket.org/) is already using Parcel 2 in production, which improved their time-to-interactive metric by ~10% over their previous webpack-based build setup. In addition, Parcel's cache has improved development iteration speed, reducing the amount of time developers spend waiting for builds.

**Microsoft** is using Parcel 2 to build parts of the [docs.microsoft.com](https://docs.microsoft.com) website.

… and [many more](https://twitter.com/devongovett/status/1435638978665799683) as well!

## What's new since the RC release?

Since our [last release](/blog/rc0/), we’ve mainly focused on bug fixes and documentation, but there have been a number of new features added as well.

### First-class SVG support

Parcel now has full SVG support, including support for external dependencies referenced by tags such as `` and ``, as well as scripts and styles. It processes all of these references through the relevant pipeline (e.g. optimizing images and minifying CSS), and the URL is rewritten to match the output filename (e.g. including a content hash).

Parcel also processes inline `<script>` and `<style>` elements, as well as the `style` attribute, and presentation attributes like `fill`.

SVGs can be referenced as an external file from HTML, CSS, JavaScript, or anywhere else, and Parcel also handles SVGs embedded inside HTML. In JavaScript, Parcel also supports a plugin to convert SVGs to JSX for use in frameworks like React.

Finally, Parcel also includes an optimizer based on [SVGO](https://github.com/svg/svgo) to minify SVGs and reduce their sizes.

Thanks to [Chris Wilkinson](https://github.com/thewilkybarkid) for helping to implement this!

### Image optimizer

Parcel now has lossless image optimization for JPEGs and PNGs enabled by default in production mode. This reduces the size of images without affecting their quality in any way. Depending on the input images, it can make a surprising amount of difference. For example, one PNG on our new website was optimized from **~700 KB to ~430 KB with zero quality loss**. Now you’ll always get optimized images, even if you didn’t realize they needed it!

If you want to take it to the next level, check out our docs on the Parcel [image transformer](/recipes/image/), which makes it simple to resize and convert images to modern formats like WebP and AVIF.

### Service worker runtime

Parcel has supported service workers since very early on. Just use the `navigator.serviceWorker.register` API, and Parcel automatically processes the dependency. However, until now, there hasn't been a built-in way of accessing the list of files that Parcel generates from within your service worker, which you might need to implement pre-caching.

In this release, Parcel now has a new `@parcel/service-worker` package, which you can import to gain access to a manifest of URLs, and a version hash. This makes it simple to pre-cache all of your files when the service worker is installed.

```javascript
import {manifest, version} from '@parcel/service-worker';

async function install() {
  const cache = await caches.open(version);
  await cache.addAll(manifest);
}

addEventListener('install', e => e.waitUntil(install()));
```

Check out the [Service workers](/languages/javascript/#service-workers) section in the JavaScript docs for more details!

### Gzip and Brotli compression

Gzip and Brotli compression is often done automatically by servers and CDNs, but sometimes you need to upload pre-compressed bundles ahead of time. This may also allow for better compression, which would be too slow to do on every network request.

Because not everyone needs it, compression is opt-in. Just add `@parcel/compressor-gzip` and/or `@parcel/compressor-brotli` to your `.parcelrc`. Then, you'll get `.gz` and `.br` files along with your original bundles. See [the docs](/features/production/#compression) for more details on how to set this up.

Compression is not limited to Gzip and Brotli, however. In fact, it's a whole [new plugin type](/plugin-system/compressor/) in Parcel's plugin system, which runs at the very end of the build process while writing the final files. You can write your own `Compressor` plugins to compress or encode output bundles however you like. Compressors are different from `Optimizer` plugins because they do not affect the final content hash, and you can have multiple compressors to produce multiple versions of the same bundle simultaneously.

### Scope hoisting diagnostics

Have you ever wondered why tree shaking isn't working as you expect? Did something in your code (or a library) change and suddenly your bundle sizes are larger? Now Parcel can tell you when it bails out, and exactly what caused it. Just run Parcel with the `--log-level verbose` CLI option to debug, and you'll see detailed information in your terminal. Each bailout links to a corresponding section in [the documentation](/features/scope-hoisting/#avoiding-bail-outs) with more info.



### Babel preset warnings

If you’re upgrading an existing project that is using Babel, you may see warnings like this:



By default, Parcel uses [SWC](https://swc.rs) to transpile JavaScript, which is much faster than Babel. But if you have an existing project using Babel, Parcel will still pick up your Babel config. This could be slowing down your build unnecessarily.

If you're only using `@babel/preset-env`, `@babel/preset-react`, and/or `@babel/preset-typescript`, then deleting your Babel config entirely, or disabling it from being used by Parcel can significantly improve your build performance. And even if you do have other plugins, removing the default presets and letting Parcel handle transpilation automatically can still make your build faster.

Check out [the documentation](/languages/javascript/#default-presets) for more details.

### XML transformer

While building the new Parcel website, we wanted to enable this blog to be consumed via [RSS](/feed.xml). However, since the website is processed by Parcel, all of the images and other static assets include content hashes in their URLs. This meant that references in the post content within the RSS feed needed to be processed as well so they included the correct content hash.

Parcel now has an XML transformer plugin, `@parcel/transformer-xml`, which can be used to process RSS and Atom feeds. It handles all URL references in the feed, and even processes embedded HTML content through the full Parcel HTML pipeline just like any standalone HTML page! This is a great example of the power of Parcel's fully language agnostic plugin system.

Check out [the documentation](/languages/xml/) to learn more.

## New `npm:` scheme

When resolving dependencies that are specified as URLs, e.g. in HTML, CSS, or `new URL()` in JavaScript, "bare specifiers” (i.e. not starting with `./` or `/`) are treated as relative paths. This is in contrast with dependencies in JavaScript `import` statements, which treat these specifiers as node_modules packages.

But sometimes you want to reference a file in node_modules from one of these places. Now you can. Prefix the URL with the `npm:` scheme, and it will be resolved just like a JavaScript `import` statement rather than as a relative URL. This works in `<script>` elements, CSS `url()` dependencies, and everywhere else URLs are supported.

The following example shows how you could reference an npm package directly from a script tag:

```html
<script src="npm:focus-visible"></script>
```

See [the documentation](/features/dependency-resolution/#url-schemes) for more info about the URL schemes supported by Parcel.

## Thanks

Parcel 2 has been a long process, and would not have happened without the work of the amazing core team, and all of the [contributors](https://github.com/parcel-bundler/parcel/graphs/contributors) who have been involved over the years. And thanks to everyone who has sponsored or donated on [Open Collective](https://opencollective.com/parcel) for helping us recognize their hard work.

Current:

- [Will Binns-Smith](https://twitter.com/wbinnssmith)
- [Jasper De Moor](https://twitter.com/JasperDeMoor)
- [Brian Do](https://github.com/thebriando)
- [Eric Eldredge](https://twitter.com/lettertwo)
- [Agnieszka Gawrys](https://github.com/AGawrys)
- [Devon Govett](https://twitter.com/devongovett)
- [Gora Kong](https://twitter.com/gorakong)
- [Niklas Mischkulnig](https://twitter.com/mischnic)

Alumni:

- [Jamie Kyle](http://twitter.com/buildsghost)
- [Joey Slater](https://twitter.com/TheJoeySlater)
- [Maia Teegarden](https://twitter.com/padmaia)
- [Kyle Welch](https://twitter.com/kylewelch)

## Try it out!

Though we’ve been working on it for a long time, Parcel 2 is really just getting started. We’re excited to see how you use it, and have many more features and improvements coming soon. Stay tuned!

- [GitHub](https://github.com/parcel-bundler/parcel)
- [Discord community](https://discord.gg/XSCzqGRuvr)
- [Support us on Open Collective](https://opencollective.com/parcel)

---

## File: src/blog/v2-12-0/v2-12-0.md

---
layout: layout.njk
title: Parcel v2.12.0
eleventyNavigation:
  key: blog-parcel-2-12-0
  title: Parcel v2.12.0
date: 2024-02-28
---

Parcel v2.12.0 introduces support for macros, which enable you to generate code at build time using regular JavaScript functions. It also includes a new online REPL, improves our CSS bundling support, adds configuration options to fine tune your app's code splitting, and improves performance and memory usage.

## Macros

Parcel v2.12.0 introduces support for [macros](/features/macros/). Originally implemented in [Bun](https://bun.sh/docs/bundler/macros), Macros are JavaScript functions that run at build time instead of being bundled. The value returned by a macro is inlined into the bundle in place of the original function call. This allows you to generate constants, code, and even additional assets without any custom plugins.

Macros are imported using an [import attribute](https://github.com/tc39/proposal-import-attributes) to indicate that they should run at build time rather than being bundled into the output. You can import any JavaScript or TypeScript module as a macro, including built-in Node modules and packages from npm.

This example uses the [regexgen](https://github.com/devongovett/regexgen) library to generate an optimized regular expression from a set of strings at build time.

```ts
import regexgen from 'regexgen' with {type: 'macro'};

const regex = regexgen(['foobar', 'foobaz', 'foozap', 'fooza']);
console.log(regex);
```

This compiles to the following bundle:

```js
console.log(/foo(?:zap?|ba[rz])/);
```

As you can see, the `regexgen` library has been completely compiled away, and we are left with a static regular expression!

Parcel's implementation of macros also enables you to generate functions at build time, and even emit new assets. For example, macros can generate CSS which will be statically extracted into a CSS bundle as if it was imported from the JS file.

This example accepts a string of CSS and returns a generated class name. The CSS is added as an asset and bundled into a CSS file, and the JavaScript bundle only includes the generated class name as a static string.

{% sample %}
{% samplefile "index.ts" %}

```tsx
import {css} from './css.ts' with {type: 'macro'};

<div className={css('color: red; &:hover { color: green }')}>
  Hello!
</div>
```

{% endsamplefile %}
{% samplefile "css.ts" %}

```ts
import type {MacroContext} from '@parcel/macros';

export async function css(this: MacroContext | void, code: string) {
  let className = hash(code);
  code = `.${className} { ${code} }`;

  this?.addAsset({
    type: 'css',
    content: code
  });

  return className;
}
```

{% endsamplefile %}
{% endsample %}

The bundled output of the above example would look like this:

{% sample %}
{% samplefile "index.js" %}

```tsx
<div className="ax63jk4">
  Hello!
</div>
```

{% endsamplefile %}
{% samplefile "index.css" %}

```css
.ax63jk4 {
  color: red;
  &:hover {
    color: green;
  }
}
```

{% endsamplefile %}
{% endsample %}

This is basically a CSS-in-JS library with build-time static extraction in just a few lines of code! And since macros are just regular JavaScript or TypeScript functions, you can create any API on top of this that you want, for example generating CSS using an object API or theme values. We are excited to see what innovations this unlocks – for CSS-in-JS and much more. Check out [the documentation](/features/macros/) to learn more.

## REPL

Parcel now has a [REPL](https://repl.parceljs.org/) where you can try it out right in your browser! [Niklas Mischkulnig](https://github.com/mischnic) has been working on the REPL over the course of several years, and we're excited that it's finally integrated into our website. The REPL features a full code editor, file browser, and support for most Parcel features including watch mode, dev server, hot module replacement, and more.

Under the hood, the REPL is powered by cutting edge web technologies including Web Assembly, service workers to host the dev server, a web worker backend for multi-core processing, and IndexedDB for package manager caching. It can even install packages from npm by running a compiled version of Yarn for the browser.

The REPL is great for playing around with Parcel and seeing how things are compiled. It's also great for creating shareable bug reproductions. [Check it out](https://repl.parceljs.org/)!

## Lightning CSS powered bundling

Parcel has used [Lightning CSS](https://lightningcss.dev) to transform CSS files by default for a while. Now Parcel uses it for bundling CSS files as well. This brings support for modern CSS features like `@import` with [cascade layers](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Cascade_layers), improved support for importing with media and supports queries, and more correct handling of complex CSS ordering issues.

## Manual shared bundles

By default, Parcel automatically code splits your code for maximum cache efficiency. Common modules that are shared between multiple parts of your application are extracted into a [shared bundle](/features/code-splitting/#shared-bundles) so that they can be loaded and cached separately by the browser. But sometimes, you might know more than Parcel about how a certain part of your app should be loaded, choosing to over-fetch up front in order to optimize later. In this release, we're introducing support for manual shared bundles to address this.

Manual shared bundles let you configure Parcel to ensure that certain modules are always bundled together no matter where they are used. For example, you could create a vendor bundle that loads a set of commonly used libraries, or group together the assets for a specific route into a single bundle. This is specified using globs to match against file paths, as well as additional options to group by root asset or type, split into multiple parallel http requests, and more. Check out [the documentation](/features/code-splitting/#manual-shared-bundles) for all the details.

Manual shared bundles are best applied after trying Parcel's default bundling algorithm and doing real-world performance testing. When you have a specific performance issue that can't be solved by changing your code structure, use manual shared bundles to override Parcel's default behavior. Manual shared bundles can also be useful when porting code from other bundlers like webpack.

## Performance improvements

Like most Parcel releases, v2.12.0 also includes some performance improvements. In this release, we've improved our core graph data structure to reduce memory usage by ~52%, and improve performance of writes by ~5%. For a real world, very large app, this amounts to an ~800MB reduction in memory usage with no regression in startup, build, or shutdown times! If you're interested in learning how we made these optimizations, check out [the PR](https://github.com/parcel-bundler/parcel/pull/9444). And for more background on our custom graph data structure backed by SharedArrayBuffer, we now have some [documentation](https://github.com/parcel-bundler/parcel/blob/v2/docs/AdjacencyList.md).

Also in this release, we've improved the way Parcel stores the graph to disk to work in small chunks during idle time in development rather than blocking the process from shutting down while the graph is being serialized. Instead of serializing the entire graph at once, we now track which parts have been modified and only re-serialize those. This should improve the perceived shut down performance of Parcel for very large projects.

## Thanks!

Thanks to everyone who contributed to this release! Check out the [full changelog](https://github.com/parcel-bundler/parcel/releases/tag/v2.12.0) for all of the other bug fixes and improvements.

- [GitHub](https://github.com/parcel-bundler/parcel)
- [Discord community](https://discord.gg/XSCzqGRuvr)
- [Support us on Open Collective](https://opencollective.com/parcel)

---

## File: src/blog/v2-14-0/v2-14-0.md

---
layout: layout.njk
title: Parcel v2.14.0
eleventyNavigation:
  key: blog-parcel-2-14-0
  title: Parcel v2.14.0
date: 2025-03-18
---

Parcel v2.14.0 introduces beta support for React Server Components, which can be integrated into existing client-rendered apps, server rendered at request time, or statically rendered to HTML at build time. In addition, it adds first-class MDX support, a CLI to scaffold new Parcel apps, and a new React error overlay. It also optimizes browser caching with native HTML import maps. This is a big release, so let's dive in!

## React Server Components

Parcel v2.14.0 introduces beta support for [React Server Components](/recipes/rsc/), a new type of component that renders ahead of time, on the server or at build time. Server Components seamlessly integrate client and server code in one unified component tree, helping reduce client bundle sizes by pre-rendering non-interactive components.

Unlike other RSC implementations, Parcel is not a full framework. Instead, it provides the tools you need to build your own application or framework from scratch with much less work. This gives you freedom to experiment with new patterns, or integrate Server Components into an existing app without a major rewrite.

Thanks to its existing multi-environment support, Parcel integrates server and client code in one unified module graph, building your entire app in a single command and supporting features like code splitting across environments. This includes support for the ["use client"](https://react.dev/reference/rsc/use-client) and ["use server"](https://react.dev/reference/rsc/use-server) directives to declare environment boundaries, dynamic import to load components on demand based on data, and more.

Check out our [rsc-examples](https://github.com/parcel-bundler/rsc-examples) repo for complete example apps built with React Server Components and Parcel, and see [the documentation](/recipes/rsc/) for a deep dive.

### Integrating into a client-rendered app

Parcel enables incremental adoption of Server Components within existing client-rendered React apps. For example, instead of returning JSON from an API server for a new feature, you could render Server Components. This can help reduce client bundle sizes by sending only the components needed to render the requested data, and omitting heavy non-interactive components (e.g. Markdown renderers) from the client bundle entirely.

```jsx
import express from 'express';
import {renderRSC} from '@parcel/rsc/node';

let app = express();
app.get('/comments', (req, res) => {
  renderRSC(<Comments />).pipe(res);
});

async function Comments() {
  // Load data from a database...
  let comments = await db.getComments();

  // Render Markdown and interactive Client Components
  return comments.map(comment => (
    <article key={comment.id}>
      <p>Posted by: {comment.user}</p>
      <Markdown content={comment.body} />
      <LikeButton />
    </article>
  ));
}
```

On the client, Server Components can be loaded using [React Suspense](https://react.dev/reference/react/Suspense).

```jsx
import {fetchRSC} from '@parcel/rsc/client';

function App() {
  return (
    <Suspense fallback={<>Loading comments...</>}>
      <Comments />
    </Suspense>
  );
}

let request;
function Comments() {
  request ??= fetchRSC('http://localhost:3000/comments');
  return request;
}
```

Server Components can be integrated into an existing client-rendered SPA without rewriting your whole app. Simply add a new target pointing at your server code, alongside your existing SPA. Parcel will build both targets together, and share common dependencies between them. Check out [the docs](/recipes/rsc/) to learn more.

### Server rendering

In a client-rendered React app, the entry point for your Parcel build is typically an HTML file. The output of the build might be uploaded to a static file server or CDN. After the HTML and JavaScript loads, you might request data from an API server and render it with components on the client. In the process of rendering the data, you might dynamically load additional components or data. This is a performance problem called a _network waterfall_.

<svg viewBox="0 0 570 145" style="width: 100%; max-width: 570px" fill="currentColor">
  <rect x="0" y="0" width="100" height="20" fill="#3498db" />
  <text x="105" y="15" font-size="14">HTML</text>
  <rect x="30" y="25" width="180" height="20" fill="#2ecc71" />
  <text x="215" y="40" font-size="14">JavaScript</text>
  <rect x="30" y="50" width="120" height="20" fill="#CB297B" />
  <text x="155" y="65" font-size="14">CSS</text>
  <rect x="210" y="75" width="100" height="20" fill="#F8BA00" />
  <text x="315" y="90" font-size="14">Data</text>
  <rect x="210" y="100" width="150" height="20" fill="#F8BA00" />
  <text x="365" y="115" font-size="14">Data</text>
  <rect x="360" y="125" width="130" height="20" fill="#2ecc71" />
  <text x="495" y="140" font-size="14">JavaScript</text>
</svg>

React Server Components can optimize network waterfalls by rendering to HTML as part of the initial request. This avoids additional API requests to load data, and allows components needed to render the data to be loaded in parallel instead of in series.

<svg viewBox="0 0 290 95" style="width: 100%; max-width: 290px" fill="currentColor">
  <rect x="0" y="0" width="100" height="20" fill="#3498db" />
  <text x="105" y="15" font-size="14">HTML + Data</text>
  <rect x="30" y="25" width="180" height="20" fill="#2ecc71" />
  <text x="215" y="40" font-size="14">JavaScript</text>
  <rect x="30" y="50" width="120" height="20" fill="#CB297B" />
  <text x="155" y="65" font-size="14">CSS</text>
  <rect x="30" y="75" width="130" height="20" fill="#2ecc71" />
  <text x="165" y="90" font-size="14">JavaScript</text>
</svg>

When using server rendering, the entry point for your Parcel build is the source code for your server instead of a static HTML file. Parcel v2.14.0 includes out of the box support for running Node servers in development mode. Running `parcel src/server.js` will build your server, and run it with built-in hot reloading when you make changes just like your client side code.



Check out [the docs](/recipes/rsc/#server-rendering) for more information.

### Static rendering

Parcel also supports pre-rendering React Server Components to fully static HTML at build time. For example, a marketing page or blog post is often static, and does not contain dynamic data personalized for the user. Pre-rendering allows these pages to be served directly from a CDN rather than requiring a server.

Parcel now includes a built-in static site generator powered by React Server Components out of the box. Entry components are rendered to static HTML at build time, with interactive Client Components hydrated in the browser. Parcel provides a list of all pages along with metadata about the current page to each entry component, allowing it to render site navigation. With [MDX](/recipes/rsc/#mdx), it also generates a table of contents for each page, and provides static exports as metadata. See below for more on MDX.

```jsx
export default function Page({pages, currentPage}) {
  return (
    <html>
      <head>
        <title>{currentPage.name}</title>
      </head>
      <body>
        <nav>
          {pages.map(page => (
            <a href={page.url}>{page.name}</a>
          ))}
        </nav>
      </body>
    </html>
  );
}
```

You can also mix static and dynamic pages in the same app by creating multiple targets. For example, a marketing page could be statically rendered and deployed to a CDN, and your product's dashboard could be server rendered.

See [the docs](/recipes/rsc/#static-rendering) for more details.

## First-class MDX support

Parcel now includes [first-class MDX support](/languages/mdx/) out of the box. It is written in Rust for performance using [mdx-rs](https://github.com/wooorm/mdxjs-rs), and deeply integrated with Parcel. Dependencies such as images and links in both Markdown and JSX syntax are detected and processed by Parcel, just like HTML. Custom code block components can be provided to easily implement syntax highlighting and inline rendered examples, perfect for documentation sites. MDX can also be used together with React Server Components, with an automatically extracted table of contents and metadata from static exports.

## create-parcel CLI

To help setup new projects more quickly, Parcel now includes a `create-parcel` CLI that scaffolds a project from a template. For example, to create a new React Server Components project, run the following command:

```bash
npm create parcel react-server my-rsc-app
```

This will create a new `my-rsc-app` directory, initialize a Git repo, scaffold boilerplate files, and install dependencies. Currently there are 4 templates:

* `vanilla` – a Vanilla JS + HTML app
* `react-client` – a TypeScript + React client only app. See [Parcel's React docs](/recipes/react/).
* `react-server` – a TypeScript + React Server Components app. See [Parcel's React Server Components docs](/recipes/rsc/).
* `react-static` – a TypeScript + React static site generator. See [Parcel's React Server Components docs](/recipes/rsc/).

We will add additional templates in the future for other frameworks and setups.

## Create React App migration

Recently, the React team [deprecated Create React App](https://react.dev/blog/2025/02/14/sunsetting-create-react-app) for new apps. Existing apps are encouraged to migrate to another framework or build tool like Parcel. To help make assist with this, we now have official [migration docs](/migration/cra/) describing how to migrate from CRA to Parcel. In addition, these steps are automated via our new [cra-to-parcel](https://github.com/parcel-bundler/cra-to-parcel) script.

```bash
npx cra-to-parcel
```

This migrates your dependencies, configuration, and source code to use Parcel. If you run into any issues during this process, please [file an issue on Github](https://github.com/parcel-bundler/cra-to-parcel/issues).

## New React error overlay

In React apps, Parcel includes an error overlay that displays runtime errors with a nice UI containing inline code frames. We previously used the `react-error-overlay` package from Create React App to implement this. As mentioned above, CRA is now officially deprecated, and `react-error-overlay` has been unmaintained for some time. In this release, we forked and modernized the error overlay and integrated it deeper with Parcel.

Previously, the error overlay implemented its inline code frames using source maps. When an error occured, it parsed the stack trace, loaded the relevant source maps in the browser, and mapped each line in the stack to a code frame with syntax highlighting. This is quite intensive to implement in the browser, often requiring many network round trips and expensive source map parsing logic.

The Parcel dev server now exposes an internal endpoint to do all of this, instead of doing it in the browser. This improves performance since source mapping logic can be implemented in Rust, and there are no network round trips.

In addition, with React Server Components, errors that occur in server code will also appear in the same error overlay, and React hydration errors are displayed with colorized diffs.



## Native HTML import maps

Parcel now uses native [HTML import maps](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap) to implement its bundle manifest when supported by your browser targets.

Parcel's bundle manifest helps avoid [cascading cache invalidation](https://philipwalton.com/articles/cascading-cache-invalidation/). Instead of directly referencing dynamically loaded bundles by URL which may include a changing content hash (e.g. `import("./some-bundle.fh36va.js")`), Parcel uses a stable bundle id (e.g. `import("af43fx")`). This id is mapped to a URL at runtime through a bundle manifest. This way, when the content hash of the referenced bundle changes, it does not _cascade_ to all bundles that reference it as well.

Previously, Parcel implemented a custom bundle manifest in JavaScript. This was placed in each entry JavaScript bundle of your app. Therefore, when a dynamically loaded bundle changed, only that bundle and the entry bundles would be invalidated in browser caches.

Parcel now uses native HTML import maps to implement the bundle manifest when possible. Parcel injects a `<script type="importmap">` into the HTML page containing this bundle manifest. This eliminates Parcel's custom runtime, and improves cache hit rates. Now, instead of invalidating all entry JavaScript bundles whenever any bundle changes, only the changed bundle is invalidated.

## Thanks!

Thanks to everyone who contributed to this release! Check out the [full changelog](https://github.com/parcel-bundler/parcel/releases/tag/v2.14.0) for all of the other bug fixes and improvements.

- [GitHub](https://github.com/parcel-bundler/parcel)
- [Discord community](https://discord.gg/XSCzqGRuvr)
- [Support us on Open Collective](https://opencollective.com/parcel)

---

## File: src/blog/v2-15-0/v2-15-0.md

---
layout: layout.njk
title: Parcel v2.15.0
eleventyNavigation:
  key: blog-parcel-2-15-0
  title: Parcel v2.15.0
date: 2025-05-11
---

Parcel v2.15.0 introduces a new transformer and minifier for HTML and SVG, implemented in Rust using browser-grade components from Firefox and Servo. It also reduces the number of npm dependencies by 25% and installed node_modules size by 45%.

## New HTML transformer

Since the first version of Parcel, our HTML transformer has relied on [posthtml](https://posthtml.org/). This provided an ecosystem of plugins for parsing and transforming HTML, including the [htmlnano](https://htmlnano.netlify.app) minifier.

With the ongoing tooling migration to Rust and other native languages, it was time to build a new HTML transformer for Parcel. Rust enables us to reuse high quality battle tested components from browsers, like we did for CSS with [Lightning CSS](https://lightningcss.dev). The new HTML transformer uses Servo's [html5ever](https://github.com/servo/html5ever) parser. (Correct) HTML parsing is notoriously hard. There are tons of edge cases and error handling rules described in [the spec](https://html.spec.whatwg.org/multipage/parsing.html) (which is over 100 printed pages!), developed over the course of decades. Using a browser-grade parser ensures that Parcel can handle any HTML document the same way as browsers do.

Once the HTML is parsed, Parcel traverses the DOM to find dependencies such as images, links, videos, meta tags, etc. In addition, inline `<script>` and `<style>` tags are collected. After these are processed, the HTML is updated with the final URL or contents of each asset.

The last step is minification. HTML is quite tricky to minify. Even removing whitespace is not safe in most cases. For example, a CSS stylesheet could apply `white-space: pre` which would preserve newlines and whitespace between elements. Parcel is now more conservative when minifying, prioritizing correctness over file size. However, minification of other parts of HTML is now improved. For example, quotes can be removed from attributes, boolean attribute values can be omitted, and optional closing elements can be removed (taking advantage of HTML's error recovery).

PostHTML is still supported too. When a `.posthtmlrc` file is detected, it will be applied as before. In addition, the new minifier is compatible with many options in htmlnano config files. If needed, you can also continue to use htmlnano by adding `@parcel/optimizer-htmlnano` to your `.parcelrc`.

## SVGO → OXVG

[OXVG](https://github.com/noahbald/oxvg) is a Rust-based replacement for [SVGO](https://svgo.dev) written by Noah Baldwin. It is largely compatible with SVGO config files, with [multiple times faster performance](https://github.com/noahbald/oxvg/wiki/Benchmarks) and [improved correctness](https://github.com/noahbald/oxvg/wiki/Correctness). It uses Lightning CSS to optimize styles in SVG files, and works on embedded SVGs in HTML using the same AST produced by the html5ever parser.

Your `svgo.config.json` file will continue to be used by OXVG. If you have custom plugins, or need functionality not yet supported by OXVG, you can add `@parcel/optimizer-svgo` to your `.parcelrc` to revert back to SVGO.

## SVG to JSX

Using the same parser and optimization steps described above, Parcel also supports converting [SVG to JSX](/languages/svg/#importing-as-a-react-component), for example importing icons as React components. The `@parcel/transformer-svg-jsx` plugin replaces `@parcel/transformer-svg-react`, which used [SVGR](https://react-svgr.com) for this purpose. Parcel now converts its parsed SVG DOM structure directly to an [SWC](https://swc.rs) JavaScript AST.

Most options in `svgr.config.json` files are supported by the new SVG to JSX transformer. If you have custom plugins, you can continue to use `@parcel/transformer-svg-react` instead.

## Reduced install footprint

The new HTML and SVG plugins enable us to reduce Parcel's size in node_modules by 45%, and the number of installed dependencies by 25%. We've also split our native binaries into separate packages per architecture in this release. This is less for you to update and maintain, and should lead to faster installs.

## Thanks!

Thanks to everyone who contributed to this release! Check out the [full changelog](https://github.com/parcel-bundler/parcel/releases/tag/v2.15.0) for all of the other bug fixes and improvements.

- [GitHub](https://github.com/parcel-bundler/parcel)
- [Discord community](https://discord.gg/XSCzqGRuvr)
- [Support us on Open Collective](https://opencollective.com/parcel)

---

## File: src/blog/v2-4-0/v2-4-0.md

---
layout: layout.njk
title: Parcel v2.4.0
eleventyNavigation:
  key: blog-parcel-2-4-0
  title: Parcel v2.4.0
date: 2022-03-22
---

[In January](/blog/parcel-css/), we announced [Parcel CSS](https://github.com/parcel-bundler/parcel-css), a super fast new CSS parser, compiler, and minifier written in Rust. Since then, we have been hard at work improving it, with [many new features](https://github.com/parcel-bundler/parcel-css/releases) and even better performance. Today, we're excited to announce that Parcel CSS is now the default CSS transformer and minifier in Parcel v2.4.0!

## New features

Here is a summary of some of the major features that have been added to Parcel CSS since our initial announcement.

- `@custom-media` draft syntax
- Improved minification of custom properties
- Cascade layers (i.e. `@layer`)
- Registered custom properties (i.e. `@property`)
- CSS Color Level 4, including `lab()`, and other color spaces with fallbacks for older browsers.
- `color-mix()` function from CSS Color Level 5
- Automatic vendor prefixing for `mask`, `clip-path`, and `filter`.
- And [much more](https://github.com/parcel-bundler/parcel-css/releases)!

With these features, Parcel CSS can now be used as a replacement for many common PostCSS-based setups, including autoprefixer, postcss-preset-env, postcss-modules, and cssnano.

## Upgrading

In Parcel v2.4.0, the default CSS transformer and minifier have been updated to use Parcel CSS. In most projects, this should be seamless. However, there are a few things to be aware of.

PostCSS is still fully supported, so your current configuration should still work just fine. However, we have added warnings to Parcel to notify you when we recommend updating your project's configuration to improve build performance.

### cssnano config

If you have a cssnano config file in your project, such as `.cssnanorc`, it will no longer be used by default. You may see a warning about this in the console when building your project. You can either delete this config file if you don't need it anymore, or set up a `.parcelrc` to continue using cssnano. See [the docs](/languages/css/#minification) for more details.

### autoprefixer and postcss-preset-env

In most cases, Parcel will now automatically handle vendor prefixing and transpiling CSS for your browser targets, just like it does for JavaScript. All you need to do is set up a `browserslist` field in your package.json, and Parcel will take care of the rest.

Parcel also has opt-in support for compiling draft syntax such as [nesting](/languages/css/#nesting), [custom media queries](/languages/css/#custom-media-queries), and [pseudo-class polyfills](/languages/css/#pseudo-class-replacement). See the [new docs](/languages/css/#transpilation) for more information about all of Parcel's CSS transpilation features.

If you were using autoprefixer and postcss-preset-env for this before, you may be able to remove these from your PostCSS config to improve build performance. If these were the only PostCSS plugins you were using, you can delete your PostCSS config entirely. Check out [the docs](/languages/css/#default-plugins) for more details.

### CSS modules

CSS modules are handled automatically by Parcel when named with the `.module.css` suffix. Previously, this was powered by postcss-modules under the hood, but now it is handled by Parcel CSS instead.

You can also enable all CSS files to be processed as CSS modules. Previously, this was done with the top-level `modules` option in a PostCSS config file. This option has moved to a config key in package.json for `@parcel/transformer-css`. See [the docs](/languages/css/#enabling-css-modules-globally) for more information.

### Strict parsing

The Parcel CSS parser is more strict than PostCSS. It will error when a selector, at rule, or declaration is invalid. This is useful as it avoids accidentally shipping code that is ignored when loaded in the browser.

Parcel CSS is also more spec-compliant when it comes to dependencies. If you have `url()` dependencies in CSS custom properties, you may see a new error if you reference a file by a relative path. This is ambiguous because the CSS spec actually resolves these based on where the `var()` is used, rather than where the custom property is defined. Parcel now requires that urls in custom properties are defined using absolute paths instead. See [the docs](/languages/css/#url()) for details.

## Other changes

Parcel v2.4.0 also brings several other bug fixes and improvements, including upgrades to SWC to improve JavaScript dead code elimination, and support for class static initialization blocks. Check out the [changelog](https://github.com/parcel-bundler/parcel/blob/v2/CHANGELOG.md#240---2022-03-22) to see a full list of all the improvements.

- [GitHub](https://github.com/parcel-bundler/parcel)
- [Discord community](https://discord.gg/XSCzqGRuvr)
- [Support us on Open Collective](https://opencollective.com/parcel)

---

## File: src/blog/v2-6-0/v2-6-0.md

---
layout: layout.njk
title: Parcel v2.6.0
eleventyNavigation:
  key: blog-parcel-2-6-0
  title: Parcel v2.6.0
date: 2022-05-25
---

We're happy to announce Parcel v2.6.0! This release includes new features including an error overlay for React, support for source maps in HMR, and locally scoped variables in CSS modules, along with lots of bug fixes and improvements.

## React error overlay

Parcel has included an in-browser overlay for build errors for a long time, but when a runtime error occurred, it was only logged to the console. As popularized by Create React App, Parcel now also includes a runtime error overlay for React, which shows beautiful stack traces with highlighted code frames that automatically omit React framework internals.



These code frames use source maps to show you your original code, but you can also toggle to show the compiled output if you like, or expand the collapsed framework internal stack frames as well. This is all provided by the same package that Create React App uses. Thanks to the CRA team for building such a great UI for errors!

## Launch your editor right from an error

Both the React runtime error overlay and Parcel's build error overlay now support clicking on file names or line numbers in code frames to jump straight to that line in your code editor! Parcel automatically detects which editor you're using from a list of over 15 [supported editors](https://github.com/yyx990803/launch-editor#supported-editors), based on what processes are already running or installed. This makes it super easy to jump between debugging in browser to the corresponding code in your editor.

## HMR source maps

Parcel has supported both HMR and source maps for a long time, but due to the way HMR was implemented, they didn't work together. Now, they do! This means after making changes to your code and without reloading the browser, error stack traces and console logs now show the correct line and column of your source code rather than the compiled output. This makes debugging a lot easier!

For background, Parcel implements HMR updates using a web socket, which receives the compiled code for any files that you update. This code was previously evaluated using `new Function()`, which allowed us a very fast way to update modules in place without reloading an entire script tag. Unfortunately, browsers do not have good support for source maps in this API. Now we use `eval` instead by default, which has support for source maps in Chrome and Firefox. However, Safari still does not support source maps in `eval`, so we now have a fallback of loading a `<script>` tag over HTTP from the dev server to work around this. As a side benefit, if you have a content security policy that rejects eval in development, we will also automatically fall back to loading over HTTP. This should work seamlessly, it's just a little bit slower than the eval path.

## Locally scoped variables in CSS modules

CSS modules allow you to locally scope identifiers like class names, id selectors, `@keyframes` and more within a CSS file, so that they do not conflict with identifiers in other files. However, until now, this did not include CSS variables and other dashed identifiers (e.g. `--foo`). This meant that even when using CSS modules, variable names defined in one file could clash with variables in another.

Parcel now offers an opt-in way to locally scope CSS variables and other dashed identifiers (e.g. `@font-palette-values`). When enabled, Parcel will rename CSS variables to include a hash of the filename they are in so that they don't conflict with other files. If you do need to reference a variable defined in another file, there is a new CSS syntax extension to do so:

```css
.button {
  background: var(--accent-color from "./vars.module.css");
}
```

Declaring dependencies between files explicitly also enables another cool feature: **Parcel can now tree shake unused CSS variables**! Just like with JavaScript tree shaking, Parcel tracks which CSS classes, ids, `@keyframes`, and now variables are used within each file, and automatically removes unused declarations. This is only possible with CSS modules because symbols are declared and referenced locally rather than globally. This can be a really useful feature for design systems and other libraries that have a lot of CSS variables, when perhaps only some of the available components are actually used in an application.

Check out the [updated documentation](/languages/css/#local-css-variables) to learn more about this feature.

## Custom CSS modules naming patterns

Parcel now also supports a way to configure the naming pattern used when compiling CSS modules. By default, Parcel prefixes each class name with a hash of the filename it is defined within. Now, you can define custom naming patterns by configuring `@parcel/transformer-css` in your package.json.

```json
{
  "@parcel/transformer-css": {
    "cssModules": {
      "pattern": "my-company-[name]-[hash]-[local]"
    }
  }
}
```

Check out [the docs](/languages/css/#custom-naming-patterns) to learn more.

## Globs in npm packages

The `@parcel/resolver-glob` plugin allows you to import multiple files at once using glob specifiers. Previously, it only supported local files within your project, but now you can import globs from npm packages as well.

```js
import * as locales from '@company/pkg/i18n/*.js';

console.log(locales.en.message);
```

See the [documentation](/features/dependency-resolution/#glob-specifiers) for more details.

## And more!

Parcel v2.6.0 includes a bunch of other smaller features, bug fixes, and improvements including support for `compilerOptions` and `<script setup>` for Vue, support for more image formats, updates to SWC, improved Elm error messages, and more. Check out the full [release notes](https://github.com/parcel-bundler/parcel/releases/tag/v2.6.0) for more details.

- [GitHub](https://github.com/parcel-bundler/parcel)
- [Discord community](https://discord.gg/XSCzqGRuvr)
- [Support us on Open Collective](https://opencollective.com/parcel)

---

## File: src/blog/v2-8-0/v2-8-0.md

---
layout: layout.njk
title: Parcel v2.8.0
eleventyNavigation:
  key: blog-parcel-2-8-0
  title: Parcel v2.8.0
date: 2022-11-09
---

We are excited to announce the release of Parcel v2.8.0! This release includes a brand new bundling algorithm with improved automatic code splitting, much better build performance for large projects, and fixes for many bugs. It also includes major performance improvements for HMR updates, and tree shaking changes that we've seen reduce bundle sizes by up to 50%.

## New bundling algorithm

Since our initial v2 release, Parcel has supported [automatic code splitting](/features/code-splitting/#shared-bundles), which deduplicates shared modules between multiple parts of your app (e.g. pages, dynamic imports, etc.). This allows commonly used dependencies like React or a design system to be cached independently from application code, reducing the amount of code that must be loaded when navigating between pages. Because it is automatic, it doesn't need to be configured or updated manually by developers, keeping your app optimal as you make changes.

Our initial implementation worked well on small to medium size projects, but hit scalability issues on larger projects. The algorithm involved many nested graph traversals (quadratic time complexity), and often ended up doing work which was later undone. In addition, the implementation was somewhat buggy, sometimes resulting in unnecessary duplication, or even missing modules.

The team at Atlassian has contributed a new bundling algorithm that solves these problems, significantly improving both build time and runtime performance. It takes a different approach than the previous implementation: rather than initially placing all assets into bundles based on manual code split points (e.g. dynamic import) and then removing duplication afterward, it starts with a graph containing no duplication (each asset is in only one bundle). It then combines bundles as needed to meet constraints like parallel request limits and minimum bundle size requirements. It also reduces time complexity by pre-computing more information and removing nested graph traversals.

This results in both smaller bundles and much faster builds. For a very large real-world project with over 60,000 assets, overall build time was reduced from over 25 minutes to 9 minutes (**2.7x faster**). The total bundle size for the whole project went from 952 MB to 370 MB (**2.5x smaller**). For comparison, building the same app with webpack takes over 45 minutes.

We've been working on this new bundling algorithm for a long time, and we're excited to finally make it the default in this release. Huge thanks to the Atlassian team for contributing this improvement!

## HMR rebuild performance

In addition to improving bundling performance, we have also been working on making incremental rebuilds and HMR updates even faster. This release includes three new features in this area: incremental bundling, single threaded compilation, and earlier HMR updates.

Some tools avoid bundling entirely in development by utilizing ESM in the browser to load each module individually. This means when a file changes, only that one file needs to be transformed, rather than recomputing the entire bundle. However, for large projects with many modules, this approach means the browser must make hundreds or even thousands of cascading HTTP requests on page load. Additionally, when performing an HMR update, the browser must make a network request to reload each updated file. Dependent modules must also be manually updated since there is no way of invalidating a module in the ESM module registry.

Parcel already has a development-only packager which does a lot less work than the production one (e.g. no tree shaking), but for large apps, the bundling algorithm described above could still be a bottleneck. However, most code changes are fairly simple – they affect only a single file, without adding or removing any dependencies. In these cases rebundling is unnecessary, and Parcel can now simply update the asset in place without rerunning the entire bundling algorithm. In addition, Parcel now compiles and packages on the main thread when only a single file changed to avoid the cost of serializing the bundle graph to send between workers.

This incremental bundling can make a huge difference – for example, rebuild times for the large project described above were reduced from 40 seconds to 4 seconds (**10x faster**)!

In addition, Parcel now sends HMR updates to the browser over a websocket before packaging bundles is even complete. Our custom development-only module format enables us to re-evalutate the changed modules and swap them in place with no additional network requests necessary. This effectively means HMR updates require the same amount of work as if they were not bundled, scaling with the size of the changes rather than size of the project, and avoiding network waterfalls during page load.

We've been benchmarking our end-to-end HMR update performance versus other tools. The following results show the time from saving a file to seeing updates in the browser for a React app with 1000 components:

|          | Vite    | Turbopack | Parcel     |
| -------- | ------- | --------- | ---------- |
| **Root** | 293.5ms | 274.8ms   | **88.6ms** |
| **Leaf** | 143.8ms | 57ms      | **37.4ms** |

- Parcel is 68% faster than Turbopack, and 70% faster than Vite at updating the root component.
- Parcel is 34% faster than Turbopack, and 74% faster than Vite at updating the leaf component.

See [this repo](https://github.com/devongovett/parcel-vs-vite-vs-turbopack-hmr) for full benchmark source code and results.

## Tree shaking improvements

This release also includes improvements to tree shaking with code splitting. Previously, if you used a large library containing an index file with many re-exports, Parcel would always place all of the used exports in the same bundle. For example, if you used different components from a component library on different pages or code split points (e.g dynamic import), all used components across your whole project would be placed into the entry bundles. This could mean loading much more JavaScript than necessary on initial page load.

Parcel now rewrites dependencies to point to their final destinations, following all re-exports found along the way. This means re-exports in [side effect-free packages](/features/scope-hoisting/#side-effects) now have no effect on code splitting, and only used exports within each bundle are loaded. In many applications, this means the entry bundle will become much smaller since more code will only be loaded when needed.

Results will depend on how many re-exports you rely on and your code splitting setup, but we have seen some impressive improvements in several applications so far. One very large app saw over **40% smaller JS entry bundles**, while another saw a 25% smaller JS entry and 50% smaller CSS.

Thanks to [Niklas Mischkulnig](https://twitter.com/mischnic) for contributing this improvement!

## Thanks!

Parcel v2.8.0 includes several other smaller features, bug fixes, and improvements. Check out the full [release notes](https://github.com/parcel-bundler/parcel/releases/tag/v2.8.0) for more details.

- [GitHub](https://github.com/parcel-bundler/parcel)
- [Discord community](https://discord.gg/XSCzqGRuvr)
- [Support us on Open Collective](https://opencollective.com/parcel)

---

## File: src/blog/v2-9-0/v2-9-0.md

---
layout: layout.njk
title: Parcel v2.9.0
eleventyNavigation:
  key: blog-parcel-2-9-0
  title: Parcel v2.9.0
date: 2023-05-26
---

Parcel v2.9.0 includes many long requested features, including a brand new resolver with support for package.json "exports" and tsconfig.json features, support for ESM plugins and configs, and local Parcel plugins. It also improves performance with a new default JS minifier powered by SWC, incremental symbol propagation, and improved bundler data structures, and includes a new build performance tracing feature. This is a big release – let's dive in!

## New resolver

Parcel's resolver is responsible for finding a file path for a dependency such as `import "react"`. This may seem simple, but as the JavaScript ecosystem has developed over the years, it has become more and more complex. Parcel's current resolver implementation was originally written [way back in 2018](https://medium.com/@devongovett/parcel-v1-7-0-9aac0c505837), and is missing some modern features like package.json "exports" and "imports".

Parcel v2.9.0 includes a brand new resolver implementation written from scratch in Rust. It supports all of the existing Parcel resolution features, while adding support for package.json "exports" and "imports", and tsconfig.json "baseUrl", "paths", and "moduleSuffixes".

Unfortunately, enabling support for package.json "exports" is a breaking change. When a package declares "exports", consumers can no longer import files that are not exported. In addition, due to exports conditions like "import" and "require", there is a possibility of a [dual package hazard](https://nodejs.org/api/packages.html#dual-package-hazard). For these reasons, exports support is currently opt-in and must be explicitly enabled in your project. This can be done by adding the following to your project root package.json:

```json
{
  "@parcel/resolver-default": {
    "packageExports": true
  }
}
```

Check out the documentation for [package.json exports](/features/dependency-resolution/#package-exports) and [tsconfig.json](/features/dependency-resolution/#tsconfig) to learn more about the new features!

## ESM plugins and configs

Parcel now supports plugins and config files written as native ES modules in addition to the existing support for CommonJS. This means that plugins can be published to npm using the `.mjs` format, or use `"type": "module"` in their package.json to enable ESM syntax in `.js` files. Config files such as `postcss.config.mjs` are also now supported.

This was surprisingly difficult to implement, which is why it has taken us so long. Parcel supports granular caching for everything it does to improve development performance. For this to work, it needs to track every file that is involved with your build. This includes all of the dev dependencies such as plugins, compilers, and config files that influenced the output. If any of these change, Parcel recompiles only the necessary files.

Internally, this has relied on patching Node's `require` implementation so that we can track all of the dev dependencies that are loaded. But this only works for CommonJS modules. With native ESM, there is currently no stable way to tap into the module loader in Node, which meant we couldn't track what files were imported.

To track ESM dependencies, Parcel now uses a fork of the excellent [es-module-lexer](https://github.com/guybedford/es-module-lexer) project, which is an extremely fast parser written in C, specifically designed to analyze ES module import and export syntax. We've integrated this with a Rust library that resolves those dependencies using our new resolver implementation, and collects all of the files used by an ESM plugin or config file. This allows us to invalidate the cache whenever one of these dependencies changes.

We do our best to statically analyze as much as we can, but some syntax like `import(someVariable)` isn't supported and will result in the cache being invalidated every build. You'll see a warning in those cases.

ESM support is experimental in this release. If you have feedback, please open an issue or discussion [on Github](https://github.com/parcel-bundler/parcel).

## Local plugins

Historically, Parcel v2 plugins have been required to be npm packages. Local plugins within your project were possible if you were using a monorepo, but we always encourage plugins to be published to npm or to an internal company registry so they can be reused by others. However, we heard feedback that this made building and prototyping plugins harder for projects not using a monorepo setup.

In Parcel v2.9.0, plugins can be referenced as relative paths from your `.parcelrc` config. They don't need to have their own package.json – you can reference a JavaScript file directly. Plugins hot reload when you make changes, so you don't even need to restart Parcel as you develop. While we still encourage publishing plugins to npm, this should make it easier to prototype new plugins.

You can learn more about local plugins in [the docs](/features/plugins/#local-plugins).

## SWC minifier

Parcel was one of the first tools to switch to the [SWC](https://swc.rs) JavaScript compiler, and it helped us improve performance [by 10x](/blog/beta3/) back in 2021. In Parcel v2.9.0, we are switching the default minifier from Terser to SWC as well.

The SWC minifier is around [7x faster](https://github.com/privatenumber/minification-benchmarks) than Terser, while producing comparable to even smaller output size. Most Terser configuration options are also supported by SWC, so if you have a `.terserrc` it should continue to work.

Huge thanks to the SWC team for their fantastic work improving minification performance for the whole ecosystem!

## Incremental symbol propagation

One of the main goals for Parcel from the beginning was to make rebuilds scale based on the size of the changes rather than the size of the entire project. This means it should be fast to rebuild if your project is 1 file or 100,000.
That's why we have implemented granular caching since the very first version in 2017, and why we have continued to introduce new features like [incremental bundling](/blog/v2-8-0/#hmr-rebuild-performance).

Symbol propagation is an algorithm that walks the full dependency graph of your project, and determines which exports of each module are actually used and which ones can be tree shaken away. In Parcel v2.9.0, this algorithm is now incremental. Instead of traversing over the full graph every time you make a change, it tracks what dependencies have been modified in the files you changed, and surgically updates the existing graph in place. For very large projects, this helps significantly reduce the amount of work that needs to be done each time you save a file.

Symbol propagation now also runs in development rather than only in production builds. This enables us to emit proper errors during development when you try to import something that isn't exported from a module, which can be helpful when debugging.

## Build performance tracing

Parcel now includes a `--trace` CLI flag, which will track how much time is spent in each phase of your build, which plugins were called into, and how long is spent in each. A Parcel trace can help you to optimize your build by answering questions such as, "Which plugin is taking the most time during my build?" or "Which file in my project takes the longest to transform?".

Parcel has supported a `--profile` flag for a while, which runs V8's sampling CPU profiler. `--trace` is much higher level, making it easier to see performance data at a plugin level instead of a function level. Both output data in the Chrome Tracing Format, which you can load into the Chrome Dev Tools or other more advanced analysis tools such as [Perfetto](https://ui.perfetto.dev/). There you can run SQL queries against the data to answer questions like the ones listed above.

Check out the [documentation](/features/profiling/) to learn more.

## And more!

In addition to the major features above, there were a ton more smaller features and bug fixes in this release. Check out the [full release notes](https://github.com/parcel-bundler/parcel/releases/tag/v2.9.0) for details.

Thanks to everyone who contributed to this release!

- [GitHub](https://github.com/parcel-bundler/parcel)
- [Discord community](https://discord.gg/XSCzqGRuvr)
- [Support us on Open Collective](https://opencollective.com/parcel)

---

## File: src/features/bundle-inlining.md

---
layout: layout.njk
title: Bundle inlining
eleventyNavigation:
  key: features-bundle-inlining
  title: 🪆 Bundle inlining
  order: 4
---

Parcel includes several ways to inline the compiled contents of one bundle inside another bundle.

## Inlining a bundle as text

The `bundle-text:` scheme can be used to inline the contents of a bundle as plain text. Parcel will compile the resolved file as normal, including bundling all dependencies, and then inline the result as a string into the parent bundle.

This could be used in many ways. For example, you could inline a compiled CSS bundle and use the result to inject a style tag at runtime. This might be useful in cases where you need to control where the style tag is inserted, e.g. into a Shadow DOM root.

```javascript
import cssText from 'bundle-text:./test.css';

// inject <style> tag
let style = document.createElement('style');
style.textContent = cssText;
shadowRoot.appendChild(style);
```

## Inlining as a data URL

The `data-url:` scheme allows inlining a bundle as a data URL. The resolved file will be compiled, including all dependencies, and converted to a data URL. If the file is in a binary format, it will be encoded as base 64, otherwise as a URI.

One example where this could be useful is inlining small images inside a CSS file.

```css
.foo {
  background: url(data-url:./background.png);
}
```

## Under the hood

`bundle-text:` and `data-url:` are implemented in the default Parcel config using [Named pipelines](/features/plugins/#named-pipelines). The `@parcel/transformer-inline-string` [Transformer](/plugin-system/transformer/) plugin marks the compiled asset as inline, which tells Parcel not to write the bundle to disk and instead inline it into the parent bundle. To implement data URLs, the `@parcel/optimizer-data-url` [Optimizer](/plugin-system/optimizer/) plugin is used to convert the compiled bundle to a data url.

In the Parcel config, it looks like the following. The `"..."` in each pipeline tells Parcel to run the normal transformers that match the file first, and then run `@parcel/transformer-inline-string`.

{% sample %}
{% samplefile "@parcel/config-default" %}

```json
{
  "transformers": {
    "bundle-text:*": ["...", "@parcel/transformer-inline-string"],
    "data-url:*": ["...", "@parcel/transformer-inline-string"]
  },
  "optimizers": {
    "data-url:*": ["...", "@parcel/optimizer-data-url"]
  }
}
```

{% endsamplefile %}
{% endsample %}

You can create your own named pipelines to customize inlining however you’d like, reusing the above plugins or creating custom ones. See [Parcel configuration](/features/plugins/) for more details.

Another Parcel plugin that might be useful is `@parcel/transformer-inline`. Like `@parcel/transformer-inline-string`, it marks assets as inline, but the result is not encoded as a string. This means if the inline bundle contains code, it will be *executed* in the parent bundle rather than returning a string to the user. This could be useful if you have a custom plugin that wraps the bundle somehow and needs to decode it at runtime.

For example, maybe you’d like to inline a file as an [ArrayBuffer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer), or some other custom encoding. That could be implemented using a custom Optimizer plugin, which post-processes the output of a bundle.

```javascript
import {Optimizer} from '@parcel/plugin';
import {blobToBuffer} from '@parcel/utils';

export default new Optimizer({
  async optimize({contents}) {
    let buffer = await blobToBuffer(contents);
    return {
      contents: `new Uint8Array(${JSON.stringify(Array.from(buffer))}).buffer`
    };
  }
});
```

Now you could define a named pipeline using your new plugin, and import compiled files as array buffers.

See the [Plugin system](/plugin-system/overview/) docs for more details on writing custom plugins, and the [Parcel Configuration](/features/plugins/) docs for more information about named pipelines.

## Inlining as a blob URL

You may want to inline the contents of a bundle as a [blob URL](https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL), which can be passed to many web APIs in the browser. The `@parcel/optimizer-blob-url` plugin can be used to do this, in combination `@parcel/transformer-inline`. A named pipeline for these is not included by default, so you'll need to create one in your `.parcelrc`.

{% sample %}
{% samplefile ".parcelrc" %}

```json
{
  "extends": "@parcel/config-default",
  "transformers": {
    "blob-url:*": ["...", "@parcel/transformer-inline"]
  },
  "optimizers": {
    "blob-url:*": ["...", "@parcel/optimizer-blob-url"]
  }
}
```

{% endsamplefile %}
{% endsample %}

## Inlining without transforming

In JavaScript, it’s possible to inline the contents of a file without running it through Parcel transformers first. This can be done using the `fs` Node module, which Parcel statically analyzes. It can be inlined as a string in a number of different encodings, or as a [Buffer](https://nodejs.org/api/buffer.html). See the [Node emulation](/features/node-emulation/) docs for more details.

```javascript
import fs from 'fs';

const sourceCode = fs.readFileSync(__dirname + '/foo.js', 'utf8');
```

In the above example, the `sourceCode` variable would be the contents of `foo.js` *without* being compiled, i.e. the original source code rather than the bundled result.

## Integration with other tools

Since bundle inlining is a Parcel-specific feature, you’ll need to configure other tools such as TypeScript or Flow to support it. See the [Configuring other tools](/features/dependency-resolution/#configuring-other-tools) section in the dependency resolution docs for details on how to do this.

---

## File: src/features/cli.md

---
layout: layout.njk
title: CLI
eleventyNavigation:
  key: features-cli
  title: ⌨️ CLI
  order: 9
---

The `parcel` CLI is the most common way to use Parcel. It supports three different commands: `serve`, `watch`, and `build`.

## `parcel [serve] <entries>`

The `serve` command starts a development server, which will automatically rebuild your app as you change files, and supports [hot reloading](/features/development/#hot-reloading). It accepts one or more file paths or globs as [entries](#entries). `serve` is the default command, so it may also be used by passing entries directly to `parcel`.

```bash
parcel src/index.html
```

{% warning %}

**Note**: If you have specified multiple HTML entry points and none of them has the output path `/index.html`, the dev server will respond to `http://localhost:1234/` with a 404, since Parcel doesn't know which HTML bundle is the index.

In this case, load the file directly, e.g. `http://localhost:1234/a.html` and `http://localhost:1234/b.html`.

{% endwarning %}

See [Development](/features/development/) for more details.

## `parcel watch <entries>`

The `watch` command is similar to `serve`, but does not start a dev server (only a HMR server). However, it automatically rebuilds your app as you make changes, and supports [hot reloading](/features/development/#hot-reloading). Use `watch` if you're building a library, a backend, or have your own dev (HTTP) server. See [below](#entries) for how to specify entries.

```bash
parcel watch src/index.html
```

## `parcel build <entries>`

The `build` command performs a single production build and exits. This enables [scope hoisting](/features/scope-hoisting) and other production optimizations by default. See [below](#entries) for how to specify entries.

```bash
parcel build src/index.html
```

See [Production](/features/production/) for more details.

## Entries

All Parcel commands accept one or more entries. Entries may be relative or absolute paths, or globs. They may also be directories containing a `package.json` with a `source` field. If entries are omitted entirely, the `source` field in the `package.json` in the current working directory is used. See [Entries](/features/targets/#entries) in the Targets documentation for more details.

{% warning %}

**Note**: Be sure to wrap globs in single quotes to ensure that they are not resolved by your shell and are passed to Parcel directly. This ensures that Parcel can automatically pick up newly created files matching globs without needing to restart.

{% endwarning %}

```bash
# Single file
parcel src/index.html

# Multiple files
parcel src/a.html src/b.html

# Glob (quotes required)
parcel 'src/*.html'

# Directory with package.json#source
parcel packages/frontend

# Multiple packages with a glob
parcel 'packages/*'

# Current directory with package.json#source
parcel
```

## Parameters

These parameters are supported by all Parcel commands.

| Format                                       | Description                                                                                                                                                        |
| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `--target [name]`                            | Specifies the targets to build. May be specified multiple times. See [Targets](/features/targets/).                                                                |
| `--dist-dir <dir>`                           | Output directory to write to when unspecified by targets.  Default value for the [`distDir`](/features/targets/#distdir) option in package.json `targets`.     |
| `--public-url `                         | The path prefix for absolute urls.  Default value for the [`publicUrl`](/features/targets/#publicurl) option in package.json `targets`.                        |
| `--no-source-maps`                           | Disables sourcemaps,  Overrides the [`sourceMap`](/features/targets/#sourcemap) option in package.json `targets`.                                              |
| `--config `                            | Specify which Parcel config to use.  Can be a file path or package name. Defaults to `@parcel/config-default`. See [Parcel configuration](/features/plugins/). |
| `--reporter `                  | Run the specified reporter plugin in addition to the ones specified in the `.parcelrc`. Can be specified multiple times.                                           |
| `--log-level (none/error/warn/info/verbose)` | Sets the log level.                                                                                                                                                |
| `--cache-dir `                         | Sets the cache directory. Defaults to `.parcel-cache`. See [Caching](/features/development/#caching).                                                              |
| `--no-cache`                                 | Disables reading from the filesystem cache. See [Caching](/features/development/#caching).                                                                         |
| `--profile`                                  | Runs a CPU Sampling profile during the build (a flamechart can be generated).                                                                                      |
| `--trace`                                    | Runs a [trace](/features/profiling) during the build.                                                                                                              |
| `-V, --version`                              | Outputs the version number.                                                                                                                                        |

### Parameters specific to `serve` and `watch`

| Format              | Description                                                                                                                                |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `-p, --port ` | The port for the dev server and HMR (the default port is `process.env.PORT` or 1234). See [Dev server](/features/development/#dev-server). |
| `--host <host>`     | Sets the host to listen on, defaults to listening on all interfaces.                                                                       |
| `--https`           | Runs the dev server and HMR server over [HTTPS](/features/development/#https).                                                             |
| `--cert `     | Path to a certificate to use. See [HTTPS](/features/development/#https).                                                                   |
| `--key `      | Path to a private key to use. See [HTTPS](/features/development/#https).                                                                   |
| `--no-hmr`          | Disables [hot reloading](/features/development/#hot-reloading).                                                                            |
| `--hmr-port ` | The port for the HMR server (defaults to the dev server's port). See [Hot reloading](/features/development/#hot-reloading).                |
| `--hmr-host <host>` | The host for the HMR server (defaults to the dev server's host). See [Hot reloading](/features/development/#hot-reloading).                |
| `--no-autoinstall`  | Disables [auto install](/features/development/#auto-install).                                                                              |
| `--watch-dir`       | Set the root watch directory. Useful for monorepos that have lockfiles in sub-projects.                                                    |
| `--watch-for-stdin` | Stop Parcel once stdin is closed.                                                                                                          |

### Parameters specific to `serve`

| Format             | Description                                                                                                                          |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------ |
| `--open [browser]` | Automatically opens the entry in your browser. Defaults to the default browser. See [Dev server](/features/development/#dev-server). |
| `--lazy`           | Only builds bundles requested by the dev server. See [Lazy mode](/features/development/#lazy-mode).                                  |

### Parameters specific to `build`

| Format                      | Description                                                                                                                                                                                      |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `--no-optimize`             | Disables optimizations such as minification.  Overrides the [`optimize`](/features/targets/#optimize) option of package.json `targets`. See [Production](/features/production/).             |
| `--no-scope-hoist`          | Disables scope hoisting.  Overrides the [`scopeHoist`](/features/targets/#scopehoist) option of package.json `targets`. See [Scope hoisting](/features/scope-hoisting/).                     |
| `--no-content-hash`         | Disables content hashing of output file names.  Bundle names may still include hashes, but they will not change on each build. See [Content hashing](/features/production/#content-hashing). |
| `--detailed-report [depth]` | Displays the largest 10 (number configurable with `depth`) assets per bundle in the CLI report. See [Detailed report](/features/production/#detailed-report).                                    |

---

## File: src/features/code-splitting.md

---
layout: layout.njk
title: Code Splitting
eleventyNavigation:
  key: features-code-splitting
  title: ✂️ Code Splitting
  order: 2
---

Parcel supports zero configuration code splitting out of the box. This allows you to split your application code into separate bundles which can be loaded on demand, resulting in smaller initial bundle sizes and faster load times.

Code splitting is controlled by use of the dynamic `import()` syntax, which works like the normal `import` statement, but returns a Promise. This means that the module can be loaded asynchronously.

## Using dynamic imports

The following example shows how you might use dynamic imports to load a sub-page of your application on demand.

{% sample %}
{% samplefile "pages/index.js" %}

```js
import("./pages/about").then(function (page) {
  // Render page
  page.render();
});
```

{% endsamplefile %}
{% samplefile "pages/about.js" %}

```js
export function render() {
  // Render the page
}
```

{% endsamplefile %}
{% endsample %}

Because `import()` returns a Promise, you can also use async/await syntax.

{% sample %}
{% samplefile "pages/index.js" %}

```js
async function load() {
  const page = await import("./pages/about");
  // Render page
  page.render();
}
load();
```

{% endsamplefile %}
{% samplefile "pages/about.js" %}

```js
export function render() {
  // Render the page
}
```

{% endsamplefile %}
{% endsample %}

### Tree shaking

When Parcel can determine which exports of a dynamically imported module you use, it will tree shake the unused exports from that module. This works with static property accesses or destructuring, with either `await` or Promise `.then` syntax.

{% note %}

**Note:** For the `await` cases, unused exports can unfortunately only be removed when `await` is not transpilied away (i.e. with a modern browserslist config).

{% endnote %}

{% sample null, "column" %}

{% samplefile %}

```js
let { x: y } = await import("./b.js");
```

{% endsamplefile %}


{% samplefile %}

```js
let ns = await import("./b.js");
console.log(ns.x);
```

{% endsamplefile %}

{% samplefile %}

```js
import("./b.js").then((ns) => console.log(ns.x));
```

{% endsamplefile %}

{% samplefile %}

```js
import("./b.js").then(({ x: y }) => console.log(y));
```

{% endsamplefile %}

{% endsample %}

## Shared bundles

When multiple parts of your application depend on the same common modules, they are automatically deduplicated into a separate bundle. This allows commonly used dependencies to be loaded in parallel with your application code and cached separately by the browser.

For example, if your application has multiple pages with `<script>` tags that depend on the same common modules, those modules will be split out into a "shared bundle”. This way, if a user navigates from one page to another, they only need to download the new code for that page, and not the common dependencies between the pages.

{% sample %}
{% samplefile "home.html" %}

```html
<!doctype html>
<div id="app"></div>
<script type="module" src="home.js"></script>
```

{% endsamplefile %}
{% samplefile "home.js" %}

```jsx
import { createRoot } from 'react-dom';

createRoot(app).render(<h1>Home</h1>, app);
```

{% endsamplefile %}
{% samplefile "profile.html" %}

```html
<!doctype html>
<div id="app"></div>
<script type="module" src="profile.js"></script>
```

{% endsamplefile %}
{% samplefile "profile.js" %}

```jsx
import { createRoot } from 'react-dom';

createRoot(app).render(<h1>Profile</h1>, app);
```

{% endsamplefile %}
{% endsample %}

Compiled HTML:

{% sample %}
{% samplefile "home.html" %}

```html
<!doctype html>
<div id="app"></div>
<script type="module" src="react-dom.23f6d9.js"></script>
<script type="module" src="home.fac9ed.js"></script>
```

{% endsamplefile %}
{% samplefile "profile.html" %}

```html
<!doctype html>
<div id="app"></div>
<script type="module" src="react-dom.23f6d9.js"></script>
<script type="module" src="profile.9fc67e.js"></script>
```

{% endsamplefile %}
{% endsample %}

In the above example, both `home.js` and `profile.js` depend on `react-dom`, so it is split out into a separate bundle and loaded in parallel by adding an extra `<script>` tag to both HTML pages.

This also works between different sections of an app that have been code split with dynamic `import()`. Common dependencies shared between two dynamic imports will be split out and loaded in parallel with the dynamically imported modules.

### Configuration

By default, Parcel only creates shared bundles when shared modules reach a size threshold. This avoids splitting out very small modules and creating extra HTTP requests, which have overhead even with HTTP/2. If a module is below the threshold, it will be duplicated between pages instead.

Parcel also has a maximum parallel request limit to avoid overloading the browser with too many requests at once, and will duplicate modules if this limit is reached. Larger modules are prioritized over smaller ones when creating shared bundles.

By default, these parameters have been tuned for HTTP/2. However, you can adjust these options to raise or lower them for your application. You can do this by configuring the `@parcel/bundler-default` key in the package.json in your project root.

{% sample %}
{% samplefile "package.json" %}

```json5
{
  "@parcel/bundler-default": {
    "minBundles": 1,
    "minBundleSize": 3000,
    "maxParallelRequests": 20
  }
}
```

{% endsamplefile %}
{% endsample %}

The available options are:

- **minBundles** – For an asset to be split, it must be used by more than `minBundles` bundles.
- **minBundleSize** – For a shared bundled to be created, it has to be at least `minBundleSize`bytes big (before minification and tree shaking).
- **maxParallelRequests** – To prevent overloading the network with too many concurrent requests, this ensures that a maximum of `maxParallelRequests` sibling bundles can be loaded together.
- **http** – A shorthand for setting the above values to defaults which are optimized for HTTP/1 or HTTP/2. See the table below for these default values.

| `http`                 | `minBundles` | `minBundleSize` | `maxParallelRequests` |
| ---------------------- | ------------ | --------------- | --------------------- |
| 1                      | 1            | 30000           | 6                     |
| 2 (default)            | 1            | 20000           | 25                    |

You can read more about this topic on [web.dev](https://web.dev/granular-chunking-nextjs/).

## Internalized async bundles

If a module is imported both synchronously and asynchronously from within the same bundle, rather than splitting it out into a separate bundle, the async dependency will be “internalized”. This means it will be kept within the same bundle as the dynamic import to avoid duplication, but wrapped in a `Promise` to preserve semantics.

For this reason, dynamic import is merely a *hint* that a dependency is not needed synchronously, not a guarantee that a new bundle will be created.

## Deduplication

If a dynamically imported module has a dependency that is already available in all of its possible ancestries, it will be deduplicated. For example, if a page imports a library which is also used by a dynamically imported module, the library will only be included in the parent since it will already be on the page at runtime.

## Manual shared bundles

{% warning %}

**Note**: Manual shared bundles are currently experimental and subject to change.

{% endwarning %}

By default, Parcel automatically splits commonly used modules into "shared bundles" and creates bundles in the scenarios listed above. However, in certain cases, you may want to specify exactly what goes into a bundle and who can request that bundle.

These scenarios include but are not limited to...

- Porting over your config from another build tool or bundler to Parcel
- Reducing your HTTP requests without duplicating assets, in favor of over-fetching
  - Over-fetching and loading fewer bundles overall can benefit measurements like [time-to-interactive](https://web.dev/articles/tti), especially for very large projects.
- Creating an optimized shared bundle for a specific route or set of modules

Manual Shared Bundles can be specified in your project root `package.json`. The `assets` property must be set to a list of globs. Any asset file paths matching these globs will be included in the manual shared bundle.

This example creates a vendor bundle which includes all JS assets in the graph starting from `manual.js`, split into 3 parallel HTTP requests.

{% sample %}
{% samplefile "package.json" %}

```json5
{
  "@parcel/bundler-default": {
   "manualSharedBundles": [
      {
        "name": "vendor",
        "root": "manual.js",
        "assets": ["**/*"],
        "types": ["js"],
        "split": 3
      },
    ],
  },
}
```

{% endsamplefile %}
{% endsample %}

The full list of options are as follows:

- **name** (optional) - Sets field `manualSharedBundle` on bundle to \<name\>, this can be read in a custom reporter or namer for development purposes
- **root** (optional) - Narrows the scope of the glob to the file specified. In the example above, the glob, `**/*` will match all imports within `manual.js`
- **assets** (required) - glob for Parcel to match on. Files that match the glob will be placed into a singular bundle, and deduplicated across the project unless otherwise specified. If no `root` is specified, Parcel attempts to match the glob **globally**.
- **types** (optional) - Limits globs to only match on a certain type. This field must be set if your `root` file imports multiple types (e.g. JS and CSS) or if the `assets` glob can match different types. A bundle can only contain assets of the same type.
  - A **root** file can contain imports of multiple types. Make sure to add an object in the `manualSharedBundle` array per type.
- **split** (optional) - splits the manual bundle into x bundles. 
  - For very large bundles, splitting into multiple parallel HTTP requests can improve measurements like CHR (cache hit ratio), as a smaller bundle is invalidated for a given change. 


{% warning %}

**Be careful!**

Configuring manual shared bundles overrides all automatic code splitting normally done by Parcel, and can cause unintended load-order issues as it maps on your **entire** code base, **including** `node_modules`. Be mindful of the globs you use, only specify 1 bundle per file type, and we recommend you specify a **root** file. 

{% endwarning %}

---

## File: src/features/dependency-resolution.md

---
layout: layout.njk
title: Dependency resolution
eleventyNavigation:
  key: features-dependency-resolution
  title: 📔 Dependency resolution
  order: 3
---

As Parcel builds your source code, it discovers **dependencies**, which allow code to be broken into separate files and reused in multiple places. Dependencies describe where to find the file containing the code you rely on, as well as metadata about how to build it.

## Dependency specifiers

A **dependency specifier** is a string that describes the location of a dependency relative to the file that imports it. For example, in JavaScript the `import` statement or `require` function may be used to create dependencies. In CSS, `@import` and `url()` may be used. Typically, these dependencies do not specify a full absolute path, but rather a shorter specifier that is resolved to an absolute path by Parcel and other tools.

Parcel implements an enhanced version of the [Node module resolution algorithm](https://nodejs.org/api/modules.html#modules_all_together). It is responsible for turning a dependency specifier into an absolute path that can be loaded from the file system. In addition to the standard dependency specifiers supported across many tools, Parcel also supports some additional specifier types and features.

### Relative specifiers

Relative specifiers start with `.` or `..`, and resolve a file relative to the importing file.

{% sample %}
{% samplefile "/path/to/project/src/client.js" %}

```javascript
import './utils.js';
import '../constants.js';
```

{% endsamplefile %}
{% endsample %}

In the above example, the first import would resolve to `/path/to/project/src/utils.js` and the second would resolve to `/path/to/project/constants.js`.

#### File extensions

It is recommended to include the full file extension in all import specifiers. This both improves dependency resolution performance and reduces ambiguity.

That said, for compatibility with CommonJS in Node, and with TypeScript, Parcel allows the file extension to be omitted for certain file types. The file extensions that may be omitted include `.ts`, `.tsx`, `.mjs`, `.js`, `.jsx`, `.cjs`, and `.json`. A file extension is required to import all other file types.

The following example resolves to the same files as above.

{% sample %}
{% samplefile "/path/to/project/src/client.js" %}

```javascript
import './utils';
import '../constants';
```

{% endsamplefile %}
{% endsample %}

Note that these may only be omitted when importing from a JavaScript or TypeScript file. File extensions are always required for dependencies defined in other file types like HTML and CSS.

In TypeScript files, Parcel will also try replacing JavaScript extensions including `.js`, `.jsx`, `.mjs`, and `.cjs` with their TypeScript equivalents (`.ts`, `.tsx`, `.mts`, and `.cts`). For example, a dependency on `./foo.js` will resolve to `./foo.ts`. This matches TSC's behavior. However, unlike TSC, if the original `./foo.js` exists, it will be used instead of the TS version, matching the behavior of Node and other bundlers.

#### Directory index files

In JavaScript, Typescript, and other JS-based languages, dependency specifiers may resolve to a directory rather than a file. If the directory contains a `package.json` file, the main entry will be resolved as described in the [Package entries](#package-entries) section. If no `package.json` is present, it will attempt to resolve to an index file within the directory, such as `index.js` or `index.ts`. All extensions listed above are supported for index files.

{% sample %}
{% samplefile "/path/to/project/src/app.js" %}

```javascript
import './client';
```

{% endsamplefile %}
{% endsample %}

For example, if `/path/to/project/src/client` were a directory, the above specifier could resolve to `/path/to/project/src/client/index.js`.

### Bare specifiers

Bare specifiers start with any character except `.`, `/`, `~`, or `#`. In JavaScript, TypeScript, and other JS-based languages, they resolve to a package in `node_modules`. For other types of files, such as HTML and CSS, bare specifiers are treated the same way as [relative specifiers](#relative-specifiers).

{% sample %}
{% samplefile "/path/to/project/src/client/index.js" %}

```javascript
import 'react';
```

{% endsamplefile %}
{% endsample %}

In the above example, `react` may resolve to something like `/path/to/project/node_modules/react/index.js`. The exact location will depend on the location of the `node_modules` directory, as well as configuration within the package.

`node_modules` directories are searched upwards from the importing file. The search stops at the project root directory. For example, if the importing file was at `/path/to/project/src/client/index.js` the following locations would be searched:

- `/path/to/project/src/client/node_modules/react`
- `/path/to/project/src/node_modules/react`
- `/path/to/project/node_modules/react`

Once a module directory is found, the package entry is resolved. See [Package entries](#package-entries) for more details on this process.

#### Package sub-paths

Bare specifiers may also specify a sub-path within a package. For example, a package may publish multiple entry points rather than only a single one.

```javascript
import 'lodash/clone';
```

The above example resolves `lodash` within a `node_modules` directory as described above, and then resolves the `clone` module within the package rather than its main entrypoint. This could be a `node_modules/lodash/clone.js` file, for example.

#### Builtin modules

Parcel includes shims for many builtin Node.js modules, e.g. `path` and `url`. When a dependency specifier references one of these module names, the builtin module is preferred over any module installed in `node_modules` with the same name. When building for a node environment, builtin modules are excluded from the bundle, otherwise a shim is included. See the [Node docs](https://nodejs.org/dist/latest-v16.x/docs/api/) for a full list of builtin modules.

When building for an Electron environment, the `electron` module is also considered a builtin and excluded from the bundle.

### Absolute specifiers

Absolute specifiers start with `/`, and resolve a file relative to the project root. The **project root** is the base directory of your project, which would typically contain a package manager lock file (e.g. `yarn.lock` or `package-lock.json`), or a source control directory (e.g. `.git`). Absolute specifiers could be useful to avoid very long relative paths in deeply nested hierarchies.

```javascript
import '/src/client.js';
```

The above example could be placed in any file, at any point in your project’s directory structure, and will always resolve to `/path/to/project/src/client.js`.

### Tilde specifiers

Tilde specifiers start with `~`, and resolve relative to the nearest package root from the importing file. A **package root** is a directory with a `package.json` file, which would typically be found in `node_modules`, or as the root of a package in a monorepo. Tilde specifiers are useful for similar purposes as absolute specifiers, but are more useful when you have more than one package.

{% sample %}
{% samplefile "/path/to/project/packages/frontend/src/client/index.js" %}

```javascript
import '~/src/utils.js';
```

{% endsamplefile %}
{% endsample %}

The above example would resolve to `/path/to/project/packages/frontend/src/utils.js`.

### Hash specifiers

Hash specifiers start with the `#` character, and the behavior depends on the file type they are contained within. In JavaScript and TypeScript files, hash specifiers are treated as internal package imports, described below. In other files, these are treated as relative URL hashes.

The `"imports"` field in `package.json` can be used to define private mappings that apply to import specifiers in JavaScript or TypeScript files within the package. This allows a package to define conditional imports depending on the environment, as documented [below](#package-exports) and in the [Node.js docs](https://nodejs.org/dist/latest/docs/api/packages.html#subpath-imports).

{% sample %}
{% samplefile "/path/to/project/package.json" %}

```json
{
  "imports": {
    "#dep": {
      "node": "dep-node",
      "browser": "dep-browser"
    }
  }
}
```

{% endsamplefile %}
{% samplefile "/path/to/project/src/index.js" %}

```javascript
import '#dep';
```

{% endsamplefile %}
{% endsample %}

### Query parameters

Dependency specifiers may also include query parameters, which specify transformation options for the resolved file. For example, you can specify the width and height to resize an image when loading it.

```css
.logo {
  background: url(logo.png?width=400&height=400);
}
```

See the [Image transformer](/recipes/image/) docs for more details on images. You can also use query parameters in custom [Transformer](/plugin-system/transformer/) plugins.

{% note %}

**Note**: Query parameters are not supported for CommonJS specifiers (created by the `require` function).

{% endnote %}

### URL schemes

Dependency specifiers may use URL schemes to target [Named pipelines](/features/plugins/#named-pipelines). These allow you to specify a different pipeline to compile a file with than the default one. For example, the `bundle-text:` scheme can be used to inline a compiled bundle as text. See [Bundle inlining](/features/bundle-inlining/) for more details.

There are a few reserved URL schemes that may not be used for named pipelines, and have builtin behavior.

- `node:` – an alternative way of specifying a builtin Node module. See [Builtin modules](#builtin-modules).
- `npm:` – a way for URL dependencies (e.g. in HTML, CSS, or web workers) to import files from a `node_modules` package.
- `http:` and `https:` – a fully qualified URL dependency. These are resolved at runtime, and left untouched by Parcel.
- `data:` – A [data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs) including the dependency source code inline. Currently not implemented by Parcel, but reserved for future use.
- `file:` – A [file URL](https://datatracker.ietf.org/doc/html/rfc8089). Reserved for future use.
- `mailto:` and `tel:` - Commonly used URL schemes. These are left untouched by Parcel.

### Glob specifiers

Parcel supports importing multiple files at once via globs, however, since glob imports are non-standard, they are not included in the default Parcel config. To enable them, add `@parcel/resolver-glob` to your `.parcelrc`.

{% sample %}
{% samplefile ".parcelrc" %}

```json
{
  "extends": "@parcel/config-default",
  "resolvers": ["@parcel/resolver-glob", "..."]
}
```

{% endsamplefile %}
{% endsample %}

Once enabled, you can import multiple files using a specifier like `./files/*.js`. This returns an object with keys corresponding to the files names.

```javascript
import * as files from './files/*.js';
```

is equivalent to:

```javascript
import * as foo from './files/foo.js';
import * as bar from './files/bar.js';

let files = {
  foo,
  bar
};
```

Specifically, the dynamic parts of the glob pattern become keys of the object. If there are multiple dynamic parts, a nested object will be returned. For example, if a `pages/profile/index.js` file existed, the following would match it.

```javascript
import * as pages from './pages/*/*.js';

console.log(pages.profile.index);
```

This also works with URL schemes like `bundle-text:`, as well as with dynamic import. When using dynamic import, the resulting object will include a mapping of filenames to functions. Each function can be called to load the resolved module. This means that each file is loaded on demand rather than all up-front.

```javascript
let files = import('./files/*.js');

async function doSomething() {
  let foo = await files.foo();
  let bar = await files.bar();
  return foo + bar;
}
```

Globs may also be used to import files from npm packages:

```js
import * as locales from '@company/pkg/i18n/*.js';

console.log(locales.en.message);
```

Glob imports also work with CSS:

```css
@import "./components/*.css";
```

is equivalent to:

```css
@import "./components/button.css";
@import "./components/dropdown.css";
```

## Package entries

When resolving a package directory, the `package.json` file is consulted to determine the package entry. Parcel checks the following fields (in order):

- `source` – If the module is behind a symlink (e.g. in a monorepo, or via `npm link`), then Parcel uses the `source` field to compile the module from source. The `source` field can also be used as an alias mapping if a package has multiple entry points – see [Aliases](#aliases) below for details.
- `exports` – [Package exports](#package-exports), see below for details.
- `browser` – A browser-specific version of a package. If building for a [browser environment](/features/targets/#environments), the browser field overrides other fields. The `browser` field can also be used as an alias mapping if a package has multiple entry points – see [Aliases](#aliases) below for details.
- `module` – An ES module version of the package.
- `main` – A CommonJS version of the package.

If none of these fields are set, or the files they point to do not exist, then resolution falls back to an index file. See [Directory index files](#directory-index-files) for more details.

## Package exports

The `"exports"` field in `package.json` can be used to define the publically accessible entrypoints for a package. These can also define conditional behavior based on the environment, allowing resolution to change depending on where a module is imported from (e.g. node or browser).

### Enabling package exports

Package exports are disabled by default because they may break existing projects that weren't designed with them in mind. You can enable support by adding the following to the `package.json` file in your project root directory.

{% sample %}
{% samplefile "/path/to/project/package.json" %}

```json
{
  "@parcel/resolver-default": {
    "packageExports": true
  }
}
```

{% endsamplefile %}
{% endsample %}

### Single export

If a package has only a single exported module, the `"exports"` field may be defined as a string:

{% sample %}
{% samplefile "package.json" %}

```json
{
  "name": "foo",
  "exports": "./dist/index.js"
}
```

{% endsamplefile %}
{% endsample %}

When a user imports the `"foo"` package in the above example, the `node_modules/foo/dist/index.js` module will be resolved.

### Multiple exports

If a package exports multiple modules, the `"exports"` field can provide mappings defining where to find each of these exports. The `"."` export defines the main entry point, and other entries are defined as subpaths.

{% sample %}
{% samplefile "package.json" %}

```json
{
  "name": "foo",
  "exports": {
    ".": "./dist/index.js",
    "./bar": "./dist/bar.js"
  }
}
```

{% endsamplefile %}
{% endsample %}

With the above package, a user may import `"foo"`, which resolves to `node_modules/foo/dist/index.js`, or `"foo/bar"`, which resolves to `node_modules/foo/dist/bar.js`.

{% warning %}

Any subpath that is not explicitly exported by a package containing the `"exports"` field will not be accessible by a consumer. For example, attempting to import `"foo/abc"` in the above package would result in a build time error.

{% endwarning %}

The `*` character may be used within an exports mapping as a wildcard. Only one `*` may appear in the lefthand side of the mapping, and the matched string is replaced into each instance in the righthand side. This allows you to avoid manually listing every file you want to export.

{% sample %}
{% samplefile "package.json" %}

```json
{
  "name": "foo",
  "exports": {
    "./*": "./dist/*.js"
  }
}
```

{% endsamplefile %}
{% endsample %}

In the above example, all `.js` files in the `dist` directory are exported from the package, without their extension. For example, importing `"foo/bar"` would resolve to `node_modules/foo/dist/bar.js`.

### Conditional exports

The `"exports"` field may also define different mappings for the same specifier in different [environments](/features/targets/#environments) or other conditions. For example, a package may provide different entrypoints for ES modules and CommonJS, or for Node and browsers.

{% sample %}
{% samplefile "package.json" %}

```json
{
  "name": "foo",
  "exports": {
    "node": "./dist/node.js",
    "default": "./dist/default.js"
  }
}
```

{% endsamplefile %}
{% endsample %}

In the above example, if a consumer imports the `"foo"` module from a Node environment, it will resolve to `node_modules/foo/dist/node.js`, otherwise it will resolve to `node_modules/foo/default.js`.

Conditional exports may also be nested within subpath mappings.

{% sample %}
{% samplefile "package.json" %}

```json
{
  "name": "foo",
  "exports": {
    "./bar": {
      "node": "./dist/bar-node.js",
      "default": "./dist/bar-default.js"
    }
  }
}
```

{% endsamplefile %}
{% endsample %}

This allows importing `"foo/bar"` to resolve to a different file for Node and other environments.

Conditional exports may also be nested within each other to create more complex logic.

{% sample %}
{% samplefile "package.json" %}

```json
{
  "name": "foo",
  "exports": {
    "node": {
      "import": "./dist/node.mjs",
      "require": "./dist/node.cjs"
    },
    "default": "./dist/default.js"
  }
}
```

{% endsamplefile %}
{% endsample %}

The above example defines different versions of the module depending on whether the package is loaded via ESM `import` or CommonJS `require` within a Node environment.

Parcel supports the following exports conditions:

* `"import"` – Package was referenced using the ESM `import` syntax.
* `"require"` – Package was referenced using the CommonJS `require` function.
* `"module"` – Package was referenced from either the ESM `import` syntax or the CommonJS `require` function.
* `"sass"` – Package was referenced from a Sass stylesheet.
* `"less"` – Package was referenced from a Less stylesheet.
* `"stylus"` – Package was referenced from a Stylus stylesheet.
* `"style"` – Package was referenced from a stylesheet (e.g. CSS, Sass, Stylus, etc.).
* `"node"` – Output will run in a Node environment.
* `"browser"` – Output will run in a browser environment.
* `"worker"` – Output will run in a web worker or service worker environment.
* `"worklet"` – Output will run in a worklet environment.
* `"electron"` – Output will run in an Electron environment.
* `"development"` – Package was loaded in a development build.
* `"production"` – Package was loaded in a production build.
* `"default"` – The default condition in case no other conditions matched.

{% note %}

The order that exports conditions are resolved follows the order they are defined in the package.json, not the order they are listed above.

{% endnote %}

### More examples

For more details about package.json exports, see the [Node.js documentation](https://nodejs.org/dist/latest/docs/api/packages.html#package-entry-points).

## Aliases

An alias can be used to override the normal resolution of a dependency. For example, you may want to override a module with a different but API-compatible replacement, or map a dependency to a global variable defined by a library loaded from a CDN.

Aliases are defined via the `alias` field in package.json. They can be defined either locally in the nearest `package.json` to the source file containing the dependency, or globally in the `package.json` in the project root directory. Global aliases apply to all files and packages in the project, including those in `node_modules`.

### Package aliases

Package aliases map a `node_modules` dependency to a different package, or to a local file within your project. For example, to replace `react` and `react-dom` with Preact across both files in your project as well as any other libraries in `node_modules`, you could define a global alias in the `package.json` in your project root directory.

{% sample %}
{% samplefile "package.json" %}

```json
{
  "alias": {
    "react": "preact/compat",
    "react-dom": "preact/compat"
  }
}
```

{% endsamplefile %}
{% endsample %}

You can also map a module to a file within your project by using a relative path from the `package.json` in which the alias is defined.

{% sample %}
{% samplefile "package.json" %}

```json
{
  "alias": {
    "react": "./my-react.js"
  }
}
```

{% endsamplefile %}
{% endsample %}

Aliasing only certain [sub-paths](#package-sub-paths) of a module is also supported. This example will alias `lodash/clone` to `tiny-clone`. Other imports within the `lodash` package will be unaffected.

{% sample %}
{% samplefile "package.json" %}

```json
{
  "alias": {
    "lodash/clone": "tiny-clone"
  }
}
```

{% endsamplefile %}
{% endsample %}

This also works the other way: if an entire module is aliased, then any sub-path imports of that package will be resolved within the aliased module. For example, if you aliased `lodash` to `my-lodash` and imported `lodash/clone`, this would resolve to `my-lodash/clone`.

### File aliases

Aliases can also be defined as relative paths to replace a specific file within a package with a different file. This can be done using the `alias` field to replace the file unconditionally, or with the `source` or `browser` fields to do conditionally. See [Package entries](#package-entries) above for details about these fields.

For example, to replace a certain file with a browser-specific version, you could use the `browser` field.

{% sample %}
{% samplefile "package.json" %}

```json
{
  "browser": {
    "./fs.js": "./fs-browser.js"
  }
}
```

{% endsamplefile %}
{% endsample %}

Now, if `my-module/fs.js` is imported in a browser environment, they'll actually get `my-module/fs-browser.js`. This applies both to imports from outside (e.g. [package sub-paths](#package-sub-paths)), as well as internally within the module.

### Glob aliases

File aliases can also be defined using globs, which allows replacing many files using a single pattern.  The replacement can include patterns such as `$1` to access the captured glob matches. This can be done using the `alias` field to replace files unconditionally, or with the `source` or `browser` fields to do conditionally. See [Package entries](#package-entries) above for details about these fields.

For example, you could use the `source` field to provide a mapping between compiled code in a package and the original source code. When the module is symlinked, or within a monorepo, this will allow Parcel to compile the module from source rather than use the pre-compiled version.

{% sample %}
{% samplefile "package.json" %}

```json
{
  "source": {
    "./dist/*": "./src/$1"
  }
}
```

{% endsamplefile %}
{% endsample %}

Now, any time a file in the `dist` directory is imported, the corresponding file in the `src` folder will be loaded instead.

### Shim aliases

Files or packages can be aliased to `false` to be excluded from the build, and replaced with an empty module. This could be useful to exclude certain modules from browser builds that only work in Node.js, for example.

{% sample %}
{% samplefile "package.json" %}

```json
{
  "alias": {
    "fs": false
  }
}
```

{% endsamplefile %}
{% endsample %}

### Global aliases

Files or packages may also be aliased to global variables that will be defined at runtime. For example, a particular library may be loaded from a CDN. Rather than bundling it, any time a dependency on that library is resolved, it will be replaced with a reference to that global variable instead of being bundled.

This can be done by creating an alias to an object with a `global` property. The following example aliases the `jquery` dependency specifier to the global variable `$`.

{% sample %}
{% samplefile "package.json" %}

```json
{
  "alias": {
    "jquery": {
      "global": "$"
    }
  }
}
```

{% endsamplefile %}
{% endsample %}

## TSConfig

Parcel supports some settings defined in TypeScript's `tsconfig.json` config file, including `baseUrl`, `paths`, and `moduleSuffixes`. Parcel searches upward from the file containing the dependency to find the nearest `tsconfig.json` file. It also supports using the [`extends`](https://www.typescriptlang.org/tsconfig#extends) option to merge the settings from multiple tsconfigs together. See the [TypeScript docs](https://www.typescriptlang.org/tsconfig) for more details.

### `baseUrl`

The `baseUrl` field defines the base directory from which to resolve [bare specifiers](#bare-specifiers).

{% sample %}
{% samplefile "tsconfig.json" %}

```json
{
  "compilerOptions": {
    "baseUrl": "./src"
  }
}
```

{% endsamplefile %}
{% samplefile "src/App.js" %}

```js
import 'Home';
```

{% endsamplefile %}
{% endsample %}

In the above example, `Home` will resolve to `src/Home.js` if it exists. Otherwise, it will fall back to `node_modules/Home`, for example.

### `paths`

The `paths` field can be used to define mappings from [bare specifiers](#bare-specifiers) to file paths. You can also define wildcard patterns using the `*` character.

 File paths referenced in the `paths` field are relative to the `baseUrl` if defined, otherwise to the directory containing the `tsconfig.json` file.

{% sample %}
{% samplefile "tsconfig.json" %}

```json
{
  "compilerOptions": {
    "paths": {
      "jquery": ["./vendor/jquery/dist/jquery"],
      "app/*": ["./src/app/*"]
    }
  }
}
```

{% endsamplefile %}
{% samplefile "src/App.js" %}

```js
import 'jquery';
import 'app/foo';
```

{% endsamplefile %}
{% endsample %}

In the above example, `jquery` resolves to `./vendor/jquery/dist/jquery.js`, and `app/foo` resolves to `./src/app/foo.js`.

### `moduleSuffixes`

The `moduleSuffixes` field allows you to specify the file name suffixes to search for when resolving a module.

{% sample %}
{% samplefile "tsconfig.json" %}

```json
{
  "compilerOptions": {
    "moduleSuffixes": [".ios", ".native", ""]
  }
}
```

{% endsamplefile %}
{% samplefile "src/App.js" %}

```js
import './foo';
```

{% endsamplefile %}
{% endsample %}

In the above example, Parcel will look for `./foo.ios.ts`, `./foo.native.ts`, and `./foo.ts` (in addition to other extensions like `.tsx`, `.js`, etc.).

## Configuring other tools

This section covers how to configure other tools to work with Parcel’s extensions to the Node resolution algorithm.

### TypeScript

TypeScript will need to be configured to support Parcel features like absolute and tilde dependency specifiers, and aliases. This can be done using the `paths` option in `tsconfig.json`. See the [TypeScript Module Resolution docs](https://www.typescriptlang.org/docs/handbook/module-resolution.html) for more information.

For example, to map tilde paths to the root directory, this configuration could be used:

{% sample %}
{% samplefile "tsconfig.json" %}

```json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "~*": ["./*"]
    }
  }
}
```

{% endsamplefile %}
{% endsample %}

Support for [URL schemes](#url-schemes) can also be enabled by creating an [ambient module](https://www.typescriptlang.org/docs/handbook/modules.html#ambient-modules) declaration in your project. For example, to map dependencies loaded with the `bundle-text:` scheme to a string, you could use the following declaration. This can be placed in a file such as `parcel.d.ts` anywhere in your project.

{% sample %}
{% samplefile "parcel.d.ts" %}

```typescript
declare module 'bundle-text:*' {
  const value: string;
  export default value;
}
```

{% endsamplefile %}
{% endsample %}

### Flow

Flow needs to be configured to support absolute and tilde specifiers, and aliases. This can be done using the [module.name_mapper](https://flow.org/en/docs/config/options/#toc-module-name-mapper-regex-string) feature in your `.flowconfig`.

For example, to map absolute specifiers to resolve from the project root, this configuration could be used:

{% sample %}
{% samplefile ".flowconfig" %}

```
[options]
module.name_mapper='^\/\(.*\)$' -> '<PROJECT_ROOT>/\1'
```

{% endsamplefile %}
{% endsample %}

To enable [URL schemes](#url-schemes), you'll need to create a mapping to a `.flow` [declaration file](https://flow.org/en/docs/declarations/) which exports the expected type. For example, to map dependencies loaded with the `bundle-text:` scheme to a string, you could create a file called `bundle-text.js.flow` and map all dependencies referencing the scheme to it.

{% sample %}
{% samplefile "bundle-text.js.flow" %}

```javascript
// @flow
declare var value: string;
export default value;
```

{% endsamplefile %}
{% samplefile ".flowconfig" %}

```
[options]
module.name_mapper='^bundle-text:.*$' -> '<PROJECT_ROOT>/bundle-text.js'
```

{% endsamplefile %}
{% endsample %}

---

## File: src/features/development.md

---
layout: layout.njk
title: Development
eleventyNavigation:
  key: features-development
  title: 🧑‍💻 Development
  order: 1
---

Parcel includes a development server out of the box supporting hot reloading, HTTPS, an API proxy, and more.

## Dev server

Parcel’s builtin dev server is automatically started when you run the default `parcel` command, which is a shortcut for `parcel serve`. By default, it starts a server at [http://localhost:1234](http://localhost:1234). If port `1234` is already in use, then a fallback port will be used. After Parcel starts, the location where the dev server is listening will be printed to the terminal.

The dev server supports several options, which you can specify via CLI options:

- `-p`, `--port` – Overrides the default port. The `PORT` environment variable can also be used to set the port.
- `--host` – By default, the dev server accepts connections on all interfaces. You can override this to specify that only connections from certain hosts should be accepted.
- `--open` – Automatically opens the entry in your default browser after Parcel starts. You can also pass a browser name to open a different browser, e.g. `--open safari`.
- `--no-cors` – By default, the dev server allows cross origin requests. Use this option to prevent access from external websites.

## Hot reloading

As you make changes to your code, Parcel automatically rebuilds the changed files and updates your app in the browser. By default, Parcel fully reloads the page, but in some cases it may perform Hot Module Replacement (HMR). HMR improves the development experience by updating modules in the browser at runtime without needing a whole page refresh. This means that application state can be retained as you change small things in your code.

CSS changes are automatically applied via HMR with no page reload necessary. This is also true when using a framework with HMR support built in, like React (via Fast Refresh), and Vue.

If you’re not using a framework, you can opt into HMR using the `module.hot` API. This will prevent the page from being reloaded, and instead apply the update in-place. `module.hot` is only available in development, so you'll need to check that it exists before using it.

```javascript
if (module.hot) {
  module.hot.accept();
}
```

HMR works by replacing the code for a module, and then re-evaluating it and along with all of its parents. If you need to customize this process, you can hook into it using the `module.hot.accept` and `module.hot.dispose` methods. These let you save and restore state inside the new version of the module.

`module.hot.dispose` accepts a callback which is called when that module is about to be replaced. Use it to save any state to restore in the new version of the module in the provided `data` object, or cleanup things like timers that will be re-created in the new version.

`module.hot.accept` accepts a callback function which is executed when that module or any of its dependencies are updated. You can use this to restore state from the old version of the module using the data stored in `module.hot.data`.

```javascript
if (module.hot) {
  module.hot.dispose(function (data) {
    // module is about to be replaced.
    // You can save data that should be accessible to the new asset in `data`
    data.updated = Date.now();
  });

  module.hot.accept(function (getParents) {
    // module or one of its dependencies was just updated.
    // data stored in `dispose` is available in `module.hot.data`
    let { updated } = module.hot.data;
  });
}
```

## Development target

When using the dev server, only a single target can be built at once. By default, Parcel uses a development target that supports modern browsers. This means that transpilation of modern JavaScript syntax for older browsers is disabled.

If you need to test in a older browser, you can provide the `--target` CLI option to choose which of your targets to build. For example, to build the "legacy" target defined in your package.json, use `--target legacy`. If you don't have any explicit targets defined, and only have a `browserslist` in your package.json, you can use the implicit default target with `--target default`. This will result in your source code being transpiled just as it would be in production.

See the [Targets](/features/targets/) documentation for more information.

## Lazy mode

In development, it can be frustrating to wait for your entire app to build before the dev server starts up. This is especially true when working on large apps with many pages. If you’re only working on one feature, you shouldn’t need to wait for all of the others to build unless you navigate to them.

You can use the `--lazy` CLI flag to tell Parcel to defer building files until they are requested in the browser, which can significantly reduce development build times. The server starts quickly, and when you navigate to a page for the first time, Parcel builds only the files necessary for that page. When you navigate to another page, that page will be built on demand. If you navigate back to a page that was previously built, it loads instantly.

```shell
parcel 'pages/*.html' --lazy
```

This also works with dynamic `import()`, not just separate entries. So if you have a page with a dynamically loaded feature, that feature will not be built until it is activated. When it is requested, Parcel eagerly builds all of the dependencies as well, without waiting for them to be requested.

## Caching

Parcel caches everything it builds to disk. If you restart the dev server, Parcel will only rebuild files that have changed since the last time it ran. Parcel automatically tracks all of the files, configuration, plugins, and dev dependencies that are involved in your build, and granularly invalidates the cache when something changes. For example, if you change a configuration file, all of the source files that rely on that configuration will be rebuilt.

By default, the cache is stored in the `.parcel-cache` folder inside your project. You should add this folder to your `.gitignore` (or equivalent) so that it is not committed in your repo. You can also override the location of the cache using the `--cache-dir` CLI option.

Caching can also be disabled using the `--no-cache` flag. Note that this only disables _reading_ from the cache – a `.parcel-cache` folder will still be created.

## HTTPS

Sometimes, you may need to use HTTPS during development. For example, you may need to use a certain hostname for authentication cookies, or debug mixed content issues. Parcel’s dev server supports HTTPS out of the box. You can either use an automatically generated certificate, or provide your own.

To use an automatically generated self-signed certificate, use the `--https` CLI flag. The first time you load the page, you may need to manually trust this certificate in your browser.

```shell
parcel src/index.html --https
```

To use a custom certificate, you’ll need to use the `--cert` and `--key` CLI options to specify the certificate file and private key respectively.

```shell
parcel src/index.html --cert certificate.cert --key private.key
```

## API proxy

To better emulate the actual production environment when developing web apps, you can specify paths that should be proxied to another server (e.g. your real API server or a local testing server) in a `.proxyrc`, `.proxyrc.json`, `.proxyrc.js` or `.proxyrc.ts` file.

### `.proxyrc` / `.proxyrc.json`

In this JSON file, you specify an object where every key is a pattern against which the URL is matched and the value is a [`http-proxy-middleware` options](https://github.com/chimurai/http-proxy-middleware#options) object:

{% sample %}
{% samplefile ".proxyrc" %}

```js
{
  "/api": {
    "target": "http://localhost:8000/",
    "pathRewrite": {
      "^/api": ""
    }
  }
}

```

{% endsamplefile %}
{% endsample %}

This example would cause `http://localhost:1234/api/endpoint` to be proxied to `http://localhost:8000/endpoint`.

### `.proxyrc.js`/`.proxyrc.ts`

For more complex configurations, a `.proxyrc.js` or `.proxyrc.ts` file allows you to attach any [connect](https://github.com/senchalabs/connect)-compatible middleware. First, make sure you install `http-proxy-middleware` into your project. This example has the same behaviour as the `.proxyrc` version above.

{% sample %}
{% samplefile ".proxyrc.js" %}

```js
const { createProxyMiddleware } = require("http-proxy-middleware");

module.exports = function (app) {
  app.use(
    "/api",
    createProxyMiddleware({
      target: "http://localhost:8000/",
      pathRewrite: {
        "^/api": "",
      },
    })
  );
};
```

{% endsamplefile %}
{% endsample %}

If you would like to write this as an ES module instead, you can do so using a `.proxyrc.mjs` file, or by using the `"type": "module"` option in your `package.json`.

### File watcher

To support an optimal caching and development experience Parcel utilizes a very fast watcher written in C++ that integrates with low-level file watching functionality of each operating system. Using this watcher Parcel watches every file in your project root (including all `node_modules`). Based on events and metadata from these files, Parcel determines which files need to be rebuilt.

#### Known issues with file watching

##### Safe Write

Some text editors and IDE's have a feature called "safe write" that prevents data loss by taking a copy of the file and renaming it when saved. However, this feature can prevent automatic detection of file updates.

To disable safe write, use the options provided below:

- Sublime Text 3: add `atomic_save: "false"` to your user preferences.
- IntelliJ: use search in the preferences to find "safe write" and disable it.
- Vim: add `:set backupcopy=yes` to your settings.
- WebStorm: uncheck `Use "safe write"` in Preferences > Appearance & Behavior > System Settings.
- vis: add `:set savemethod inplace` to your settings.

##### Linux: No space left on device

Depending on the size of your project, and your operating system's watcher limit, this error might pop up when you're running Parcel on Linux. To resolve this issue, change the `sysctl`configuration for `fs.inotify` to have a higher value for `max_user_watches`.

You can do this by adding or changing the following lines in `/etc/sysctl.conf`:

```
fs.inotify.max_queued_events = 16384
fs.inotify.max_user_instances = 128
fs.inotify.max_user_watches = 16384
```

If this error persists you can try increasing the values even more.

##### Using Dropbox, Google Drive or other cloud storage solutions

It is best practice to not place a Parcel project in a folder that is synced to the cloud using something like Dropbox or Google Drive. These solutions create a lot of file system events that can mess with our watcher and cause unnecessary rebuilds.

## Auto install

When you use a language or plugin that isn’t included by default, Parcel will automatically install the necessary dependencies into your project for you. For example, if you include a `.sass` file, Parcel will install the `@parcel/transformer-sass` plugin. When this happens, you'll see a message in the terminal, and the new dependency will be added to the `devDependencies` in your package.json.

Parcel automatically detects which package manager you use in your project based on the lock file. For example, if `yarn.lock` is found, then Yarn will be used to install packages. If no lock file is found, then the package manager is chosen based on what is installed on your system. The following package managers are currently supported, listed in priority order:

- [Yarn](https://yarnpkg.com)
- [Pnpm](https://pnpm.io)
- [Npm](https://www.npmjs.com)

Auto install only occurs during development by default. During production builds, if a dependency is missing, the build will fail. You can also disable auto install during development using the `--no-autoinstall` CLI flag.

---

## File: src/features/features.json

{
  "tags": "Features"
}

---

## File: src/features/macros.md

---
layout: layout.njk
title: Macros
eleventyNavigation:
  key: features-macros
  title: 🌷 Macros
  order: 4
---

Macros are JavaScript functions that run at build time. The value returned by a macro is inlined into the bundle in place of the original function call. This allows you to generate constants, code, and even additional assets without any custom plugins.

Macros are imported using an [import attribute](https://github.com/tc39/proposal-import-attributes) to indicate that they should run at build time rather than being bundled into the output. You can import any JavaScript or TypeScript module as a macro, including built-in Node modules and packages from npm.

{% warning %}

**Note**: for security reasons, macros cannot be called from inside `node_modules`.

{% endwarning %}

This example uses the [regexgen](https://github.com/devongovett/regexgen) library to generate an optimized regular expression from a set of strings at build time.

```ts
import regexgen from 'regexgen' with {type: 'macro'};

const regex = regexgen(['foobar', 'foobaz', 'foozap', 'fooza']);
console.log(regex);
```

This compiles to the following bundle:

```js
console.log(/foo(?:zap?|ba[rz])/);
```

As you can see, the `regexgen` library has been completely compiled away, and we are left with a static regular expression!

## Arguments

Macro arguments are evaluated statically, which means their value must be known at build time. You can pass any JavaScript literal value, including strings, numbers, booleans, objects, etc. Simple expressions such as string concatenation, arithmetic, and comparison operators are supported as well.

```js
import {myMacro} from './macro.ts' with {type: 'macro'};

const result = myMacro({
  name: 'Devon'
});
```

However, values referencing non-constant variables, calling functions other than macros, etc. are not supported.

```js/3
import {myMacro} from './macro.ts' with {type: 'macro'};

const result = myMacro({
  name: getName() // Error: Cannot statically evaluate macro argument
});
```

### Constants

Parcel also evaluates constants declared via the `const` keyword. These may be referenced in a macro argument.

```js/2
import {myMacro} from './macro.ts' with {type: 'macro'};

const name = 'Devon';
const result = myMacro({name});
```

The result of one macro may also be passed to another macro.

```js/3
import {myMacro} from './macro.ts' with {type: 'macro'};
import {getName} from './name.ts' with {type: 'macro'};

const name = getName();
const result = myMacro({name});
```

However, if you attempt to mutate the value of a constant, this will result in an error.

```js/3
import {myMacro} from './macro.ts' with {type: 'macro'};

const arg = {name: 'Devon'};
arg.name = 'Peter'; // Error: Cannot statically evaluate macro argument

const result = myMacro({name});
```

## Return values

Macros can return any JavaScript value, including objects, strings, booleans, numbers, and even functions. These are converted into an AST and replace the original function call in your code.

{% sample %}
{% samplefile "index.ts" %}

```ts
import {getRandomNumber} from './macro.ts' with {type: 'macro'};

console.log(getRandomNumber());
```

{% endsamplefile %}
{% samplefile "macro.ts" %}

```ts
export function getRandomNumber() {
  return Math.random();
}
```

{% endsamplefile %}
{% endsample %}

The bundled output of this example looks like this:

```js
console.log(0.006024956627355804);
```

### Async macros

Macros can also return promises that resolve to any supported value. For example, you could make an HTTP request to fetch the contents of a URL at build time, and inline the result into the bundle as a string.

{% sample %}
{% samplefile "index.ts" %}

```ts
import {fetchText} from './macro.ts' with {type: 'macro'};

console.log(fetchText('http://example.com'));
```

{% endsamplefile %}
{% samplefile "macro.ts" %}

```ts
export async function fetchText(url: string) {
  let res = await fetch(url);
  return res.text();
}
```

{% endsamplefile %}
{% endsample %}

### Generating functions

Macros can return functions, which allows you to generate code at build time. Use the `new Function` constructor to generate a function dynamically from a string.

This example uses the [micromatch](https://github.com/micromatch/micromatch) library to compile a glob matching function at build time.

{% sample %}
{% samplefile "index.ts" %}

```ts
import {compileGlob} from './glob.ts' with {type: 'macro'};

const isMatch = compileGlob('foo/**/bar.js');
```

{% endsamplefile %}
{% samplefile "glob.ts" %}

```ts
import micromatch from 'micromatch';

export function compileGlob(glob) {
  let regex = micromatch.makeRe(glob);
  return new Function('string', `return ${regex}.test(string)`);
}
```

{% endsamplefile %}
{% endsample %}

The bundled output of this example looks like this:

```js
const isMatch = function(string) {
  return /^(?:foo(?:\/(?!\.)(?:(?:(?!(?:^|\/)\.).)*?)\/|\/|$)bar\.js)$/.test(string);
};
```

## Generating assets

A macro can generate additional assets which become dependencies of the JavaScript module that called it. For example, macros can generate CSS which will be statically extracted into a CSS bundle as if it was imported from the JS file.

Within a macro function, `this` is an object with Parcel-provided methods. To create an asset, call `this.addAsset` and provide the type and contents.

This example accepts a string of CSS and returns a generated class name. The CSS is added as an asset and bundled into a CSS file, and the JavaScript bundle only includes the generated class name as a static string.

{% sample %}
{% samplefile "index.ts" %}

```tsx
import {css} from './css.ts' with {type: 'macro'};

<div className={css('color: red; &:hover { color: green }')}>
  Hello!
</div>
```

{% endsamplefile %}
{% samplefile "css.ts" %}

```ts/6-10
import type {MacroContext} from '@parcel/macros';

export async function css(this: MacroContext | void, code: string) {
  let className = hash(code);
  code = `.${className} { ${code} }`;

  this?.addAsset({
    type: 'css',
    content: code
  });

  return className;
}
```

{% endsamplefile %}
{% endsample %}

The bundled output of the above example would look like this:

{% sample %}
{% samplefile "index.js" %}

```tsx
<div className="ax63jk4">
  Hello!
</div>
```

{% endsamplefile %}
{% samplefile "index.css" %}

```css
.ax63jk4 {
  color: red;
  &:hover {
    color: green;
  }
}
```

{% endsamplefile %}
{% endsample %}

## Caching

By default, Parcel caches the result of a macro until the file that calls it changes. However, sometimes, a macro may have other inputs which should invalidate the cache. For example, it might read a file, access an environment variable, etc. The `this` context within a macro function includes methods to control the caching behavior.

```ts
interface MacroContext {
  /** Invalidate the macro call whenever the given file changes. */
  invalidateOnFileChange(filePath: string): void,
  /** Invalidate the macro call when a file matching the given pattern is created. */
  invalidateOnFileCreate(options: FileCreateInvalidation): void,
  /** Invalidate the macro whenever the given environment variable changes. */
  invalidateOnEnvChange(env: string): void,
  /** Invalidate the macro whenever Parcel restarts. */
  invalidateOnStartup(): void,
  /** Invalidate the macro on every build. */
  invalidateOnBuild(): void,
}

type FileCreateInvalidation = FileInvalidation | GlobInvalidation | FileAboveInvalidation;

/** Invalidate when a file matching a glob is created. */
interface GlobInvalidation {
  glob: string
}

/** Invalidate when a specific file is created. */
interface FileInvalidation {
  filePath: string
}

/** Invalidate when a file of a specific name is created above a certain directory in the hierarchy. */
interface FileAboveInvalidation {
  fileName: string,
  aboveFilePath: string
}
```

For example, when reading a file in a macro, add the file path as an invalidation so that the calling code is recompiled whenever that file changes. In this example, whenever `message.txt` is edited, `index.ts` will be recompiled and the `readFile` macro will be called again.

{% sample %}
{% samplefile "index.ts" %}

```tsx
import {readFile} from './macro.ts' with {type: 'macro'};

console.log(readFile('message.txt'))
```

{% endsamplefile %}
{% samplefile "macro.ts" %}

```ts
import type {MacroContext} from '@parcel/macros';
import fs from 'fs';

export async function readFile(this: MacroContext | void, filePath: string) {
  this?.invalidateOnFileChange(filePath);
  return fs.readFileSync(filePath, 'utf8');
}
```

{% endsamplefile %}
{% samplefile "message.txt" %}

```
hello world!
```

{% endsamplefile %}
{% endsample %}

## Usage with other tools

Macros are just normal JavaScript functions, so they integrate with other tools easily.

### TypeScript

TypeScript supports import attributes out of the box as of version 5.3, and autocomplete and types for macros work just like regular functions.

### Babel

The [`@babel/plugin-syntax-import-attributes`](https://babeljs.io/docs/babel-plugin-syntax-import-attributes) plugin enables Babel to parse import attributes. If you're using `@babel/preset-env`, enabling the [`shippedProposals`](https://babeljs.io/docs/babel-preset-env#shippedproposals) option also enables import attributes to be parsed.

{% sample %}
{% samplefile "babel.config.json" %}

```json/5
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "shippedProposals": true
      }
    ]
  ]
}
```

{% endsamplefile %}
{% endsample %}

### ESLint

ESLint supports import attributes when using a parser such as Babel or TypeScript that supports them.

{% sample %}
{% samplefile ".eslintrc.js" %}

```js/1
module.exports = {
  parser: '@typescript-eslint/parser'
};
```

{% endsamplefile %}
{% endsample %}

### Unit testing

Unit testing macros is just like testing any other JavaScript function. One caveat is if your macro uses the `this` context described in the above sections. If you are testing a macro itself, you can mock the `this` argument to verify it is called as expected.

{% sample %}
{% samplefile "css.test.ts" %}

```ts
import {css} from '../src/css.ts';

it('should generate css', () => {
  let addAsset = jest.fn();
  let className = css.call({
    addAsset,
    // ...
  }, 'color: red');

  expect(addAsset).toHaveBeenCalledWith({
    type: 'css',
    content: '.ax63jk4 { color: red }'
  });
  expect(className).toBe('ax63jk4');
});
```

{% endsamplefile %}
{% endsample %}

When testing code that indirectly uses a macro, the macro function will be called as a normal function at runtime rather than by Parcel at compile time. In this case, the macro context that would normally be provided by Parcel won't be available. That's why the `this` argument is typed as `MacroContext | void` in the above examples and we do a runtime check to see if `this` exists. When the context isn't available, code that uses it such as `this?.addAsset` won't run, but the function should return a value as normal.

## Differences from Bun

Macros via import attributes were originally implemented in [Bun](https://bun.sh/docs/bundler/macros). Parcel's implementation is compatible with Bun's macro API for the most part, but there are a few differences:

* Parcel supports returning functions from macros.
* Parcel supports a `this` context in macros to enable generating assets and controlling caching behavior.
* Parcel does not currently support Bun's special-case return values for typed arrays, fetch `Response` objects, or `Blob` objects. You'll need to convert these to a string yourself before returning them from a macro.
* Parcel does not currently support the `"macro"` package.json `exports` condition.

---

## File: src/features/node-emulation.md

---
layout: layout.njk
title: Node Emulation
eleventyNavigation:
  key: features-node-emulation
  title: 🐢 Node Emulation
  order: 8
---

Parcel includes several features that emulate the Node.js API. This allows many modules on npm that were originally written for Node to also work in the browser. In addition, many browser modules have also adopted Node.js-based APIs for things like environment variables.

## Environment Variables

Parcel supports inlining environment variables in JavaScript. This can be used to determine the build environment (e.g. development, staging, production), inject API keys, etc.

To access an environment variable, read the corresponding property from the `process.env` object.

```js
if (process.env.NODE_ENV === 'development') {
  console.log('Happy developing!');
}
```

You can also use destructuring syntax to access multiple properties at once.

```js
let {NODE_ENV, API_TOKEN} = process.env;
```

Accessing `process.env` in any non-static ways (e.g. dynamic property lookups) is not supported.

### `NODE_ENV`

The `NODE_ENV` environment variable is automatically set by Parcel depending on the mode. When running `parcel build`, `NODE_ENV` is set to `production` by default, otherwise it is set to `development`. This can be overridden by setting `NODE_ENV` yourself (e.g. in your shell).

### `.env` files

Parcel supports loading environment variables defined in `.env` files in your project root. This supports `NAME=value` pairs separated by newlines. Lines starting with `#` are treated as comments. See [dotenv](https://github.com/motdotla/dotenv) for more details.

{% sample %}
{% samplefile ".env" %}

```ini
APP_NAME=test
API_KEY=12345
```

{% endsamplefile %}
{% endsample %}

In addition to `.env`, environment-specific overrides such as `.env.production` and `.env.development` can also be created. These are applied based on the `NODE_ENV` environment variable (including when automatically set by Parcel). Any variables that are not set in environment-specific overrides fall back to the values defined in the base `.env` file.

The `.env.local` file is also supported for local overrides of environment variables, however, it is not used when `NODE_ENV=test` so that tests produce the same result for everyone. This is also supported for environment-specific overrides, such as `.env.production.local`.

## Polyfilling & Excluding Builtin Node Modules

When targetting the browser and your code, or more likely a dependency, imports builtin Node modules such as `crypto`, `fs` or `process`, Parcel will automatically use one of the following polyfills. If no polyfill is available, then an empty module will be used instead. You can also use [aliases](/features/dependency-resolution/#aliases) to override these.

| native module | npm replacement            | native module  | npm replacement      |
| ------------- | -------------------------- | -------------- | -------------------- |
| assert        | `assert`                   | process        | `process/browser.js` |
| buffer        | `buffer`                   | punycode       | `punycode`           |
| console       | `console-browserify`       | querystring    | `querystring-es3`    |
| constants     | `constants-browserify`     | stream         | `stream-browserify`    |
| crypto        | `crypto-browserify`        | string_decoder | `string_decoder`     |
| domain        | `domain-browser`           | sys            | `util/util.js`       |
| events        | `events`                   | timers         | `timers-browserify`  |
| http          | `stream-http`              | tty            | `tty-browserify`     |
| https         | `https-browserify`         | url            | `url`                |
| os            | `os-browserify/browser.js` | util           | `util/util.js`       |
| path          | `path-browserify`          | vm             | `vm-browserify`      |
| zlib          | `browserify-zlib`          |

## Shimming Builtin Node Globals

When targetting the browser, usages of global variables that are available in Node are replaced to not break code written for Node:

- `process` is imported automatically from the `process` module, unless it's part of a `process.browser` or `process.env.FOO` expression which is replaced by a boolean or the value of the environment variable.

- `Buffer` is imported automatically from the `buffer` module.

- `__filename` and `dirname` are replaced by string literals of the asset's filepath (or the parent folder) relative to the project root.

- `global` is replaced with a reference to the global variable (behaving like the newer `globalThis`).


## Inlining fs.readFileSync

Calls to `fs.readFileSync` are replaced with the file's contents if the filepath is statically determinable and inside the project root.

- `fs.readFileSync(__dirname + "/file", "utf8")` – the contents of the file as a string. The "utf8", "utf-8", "hex", and "base64" encodings are supported.
- `fs.readFileSync(__dirname + "/file")` – a [Buffer](https://nodejs.org/dist/latest-v16.x/docs/api/buffer.html) object. Note that the Buffer polyfill is quite large so this may be undesired.

The `__dirname` and `__filename` variables can be used in the filename argument. String concatenation via the `+` operator and the `path.join` function may be used. Other functions, variables, or dynamic computations are not supported. Computed paths should always be absolute, and not rely on the current working directory.

{% sample %}
{% samplefile "index.js" %}

```js/3
import fs from "fs";
import path from "path";

const data = fs.readFileSync(path.join(__dirname, "data.json"), "utf8");
console.log(data);
```

{% endsamplefile %}
{% samplefile "data.json" %}

```json
{
  "foo": "bar"
}
```

{% endsamplefile %}
{% endsample %}

## Disabling These Features

Inlining of [environment variables](#environment-variables) and [`readFileSync` calls](#inlining-fs.readfilesync) can be disabled by creating a `@parcel/transformer-js` key in `package.json`.

{% sample %}
{% samplefile "package.json" %}

```json5
{
  "name": "my-project",
  "dependencies": {
    ...
  },
  "@parcel/transformer-js": {
    "inlineFS": false,
    "inlineEnvironment": false
  }
}
```

{% endsamplefile %}
{% endsample %}

`inlineEnvironment` can also be an array of glob strings, which allows you to filter the allowed environment variables. This is a good idea to ensure security, since third party code in node_modules can also read environment variables.

```json5
{
  "name": "my-project",
  "dependencies": {
    ...
  },
  "@parcel/transformer-js": {
    "inlineEnvironment": ["SENTRY_*"]
  }
}
```

---

## File: src/features/parcel-api.md

---
layout: layout.njk
title: Parcel API
eleventyNavigation:
  key: features-parcel-api
  title: 📚 Parcel API
  order: 10
---

The Parcel API can be used to programmatically run builds or watch a project for changes. It is the same API as is used by the Parcel CLI. Use the API when you need more flexibility, or need to integrate Parcel into another build system.

## The `Parcel` constructor

The Parcel API can be used through the `@parcel/core` package. You'll also need a default configuration, such as `@parcel/config-default`.

```shell
yarn add @parcel/core @parcel/config-default
```

Next, import this package into your program and call the `Parcel` constructor. It accepts an [`InitialParcelOptions`](/plugin-system/api/#InitialParcelOptions) object, which contains all of the options used by the Parcel CLI and a few more.

There are two required parameters:

- `entries` – A string or an array of strings describing the entry points to build. See [Entries](/features/targets/#entries).
- `config` or `defaultConfig` – A file path or package specifier for a Parcel config to use. If `config` is set, the provided config is always used and the project `.parcelrc` is ignored. If `defaultConfig` is set, the project's `.parcelrc` takes precedence, and `defaultConfig` is used as a fallback. If a relative path or package specifier is given, it is resolved relative to the project root.

{% sample %}
{% samplefile "build.mjs" %}

```javascript
import {Parcel} from '@parcel/core';

let bundler = new Parcel({
  entries: 'a.js',
  defaultConfig: '@parcel/config-default'
});
```

{% endsamplefile %}
{% endsample %}

### Targets

By default, Parcel does a development build, but this can be changed by setting the `mode` option to `production`, which enable scope hoisting, minification, etc. See [Production](/features/production/).

You can also use the `defaultTargetOptions` to set values for [Targets](/features/targets/) if they aren't configured in the project. For example, to override the default browser targets, use the `engines` option.

{% sample %}
{% samplefile "build.mjs" %}

```javascript
import {Parcel} from '@parcel/core';

let bundler = new Parcel({
  entries: 'a.js',
  defaultConfig: '@parcel/config-default',
  mode: 'production',
  defaultTargetOptions: {
    engines: {
      browsers: ['last 1 Chrome version']
    }
  }
});
```

{% endsamplefile %}
{% endsample %}

When set to an array, the `targets` option can be used to specify which of the project’s targets (as described in `package.json`) to build. For example, to only build the project’s `modern` target:

{% sample %}
{% samplefile "build.mjs" %}

```javascript
import {Parcel} from '@parcel/core';

let bundler = new Parcel({
  entries: 'a.js',
  defaultConfig: '@parcel/config-default',
  targets: ['modern']
});
```

{% endsamplefile %}
{% endsample %}

Alternatively, `targets` may be set to an object, which will override any targets defined in the project. See [Targets](/features/targets/) for more details on the available options.

{% sample %}
{% samplefile "build.mjs" %}

```javascript
import {Parcel} from '@parcel/core';

let bundler = new Parcel({
  entries: 'a.js',
  defaultConfig: '@parcel/config-default',
  mode: 'production',
  targets: {
    modern: {
      engines: {
        browsers: ['last 1 Chrome version']
      }
    },
    legacy: {
      engines: {
        browsers: ['IE 11']
      }
    }
  }
});
```

{% endsamplefile %}
{% endsample %}

### Environment variables

Environment variables such as `NODE_ENV` may be set using the `env` option. This allows variables to be set without overriding the values on `process.env`.

{% sample %}
{% samplefile "build.mjs" %}

```javascript
import {Parcel} from '@parcel/core';

let bundler = new Parcel({
  entries: 'a.js',
  defaultConfig: '@parcel/config-default',
  mode: 'production',
  env: {
    NODE_ENV: 'production'
  }
});
```

{% endsamplefile %}
{% endsample %}

### Reporters

By default, Parcel does not write any output to the CLI when you use the API. That means it won’t report status information, and provides no pretty formatting for diagnostics. These can be enabled using the `additionalReporters` option, which run in addition to any reporters specified in `.parcelrc`. The `@parcel/reporter-cli` plugin provides the default reporter used by the CLI, but you can use any other reporter plugins as well.

{% sample %}
{% samplefile "build.mjs" %}

```javascript
import {Parcel} from '@parcel/core';
import {fileURLToPath} from 'url';

let bundler = new Parcel({
  entries: 'a.js',
  defaultConfig: '@parcel/config-default',
  additionalReporters: [
    {
      packageName: '@parcel/reporter-cli',
      resolveFrom: fileURLToPath(import.meta.url)
    }
  ]
});
```

{% endsamplefile %}
{% endsample %}

## Building

Once you’ve constructed a `Parcel` instance, you can use it to build a project or watch for changes. To build once, use the `run` API. This returns a Promise, which will be resolved with a [`BuildSuccessEvent`](/plugin-system/reporter/#BuildSuccessEvent) containing the [`BundleGraph`](/plugin-system/bundler/#BundleGraph) and some other information if the build was successful, or reject with an error if it failed. Build errors have one or more [`Diagnostic`](/plugin-system/logging/#Diagnostic) objects attached to them with the details of what went wrong.

{% sample %}
{% samplefile "build.mjs" %}

```javascript
import {Parcel} from '@parcel/core';

let bundler = new Parcel({
  entries: 'a.js',
  defaultConfig: '@parcel/config-default'
});

try {
  let {bundleGraph, buildTime} = await bundler.run();
  let bundles = bundleGraph.getBundles();
  console.log(`✨ Built ${bundles.length} bundles in ${buildTime}ms!`);
} catch (err) {
  console.log(err.diagnostics);
}
```

{% endsamplefile %}
{% endsample %}

## Watching

To watch a project for changes and be notified of each rebuild, use the `watch` API. Pass a callback to be called whenever a build succeeds or fails. The callback receives an error parameter and an event object. The error parameter is only used for fatal errors during watching. Normal build failures are represented by a [`BuildFailureEvent`](/plugin-system/reporter/#BuildFailureEvent), which includes a list of [`Diagnostic`](/plugin-system/logging/#Diagnostic) objects.

`watch` also returns a subscription object, and you should call the `unsubscribe` method when you’d like to stop watching.

{% sample %}
{% samplefile "build.mjs" %}

```javascript
import {Parcel} from '@parcel/core';

let bundler = new Parcel({
  entries: 'a.js',
  defaultConfig: '@parcel/config-default'
});

let subscription = await bundler.watch((err, event) => {
  if (err) {
    // fatal error
    throw err;
  }

  if (event.type === 'buildSuccess') {
    let bundles = event.bundleGraph.getBundles();
    console.log(`✨ Built ${bundles.length} bundles in ${event.buildTime}ms!`);
  } else if (event.type === 'buildFailure') {
    console.log(event.diagnostics);
  }
});

// some time later...
await subscription.unsubscribe();
```

{% endsamplefile %}
{% endsample %}

## Dev server

The development server is included in the default Parcel config. It can be enabled by passing `serveOptions` to the `Parcel` constructor and running Parcel in watch mode. Hot reloading can be enabled by setting `hmrOptions`. A `port` is the only required option, but others such as HTTPS options may also be set.

{% sample %}
{% samplefile "build.mjs" %}

```javascript
import {Parcel} from '@parcel/core';

let bundler = new Parcel({
  entries: 'a.js',
  defaultConfig: '@parcel/config-default',
  serveOptions: {
    port: 3000
  },
  hmrOptions: {
    port: 3000
  }
});

await bundler.watch();
```

{% endsamplefile %}
{% endsample %}

## File system

Parcel uses an abstracted file system throughout core and in most plugins. By default, it relies on the Node.js `fs` API, but Parcel also has a `MemoryFS` implementation. You can use the `inputFS` option to override the file system Parcel reads source files from, and the `outputFS` option to override the file system Parcel writes output (including the cache) to.

The `MemoryFS` is located in the `@parcel/fs` package. Constructing it requires passing a `WorkerFarm` instance so that the file system can be read and written to from multiple threads. You’ll need to create a worker farm using the `createWorkerFarm` function exported from `@parcel/core`, and pass this to both the `MemoryFS` and `Parcel` constructors. When you are done, make sure to call `end` on the worker farm to allow the process to exit.

This example writes its output into an in-memory file system, and logs the contents of each built bundle.

{% sample %}
{% samplefile "build.mjs" %}

```javascript
import {Parcel, createWorkerFarm} from '@parcel/core';
import {MemoryFS} from '@parcel/fs';

let workerFarm = createWorkerFarm();
let outputFS = new MemoryFS(workerFarm);

let bundler = new Parcel({
  entries: 'a.js',
  defaultConfig: '@parcel/config-default',
  workerFarm,
  outputFS
});

try {
  let {bundleGraph} = await bundler.run();

  for (let bundle of bundleGraph.getBundles()) {
    console.log(bundle.filePath);
    console.log(await outputFS.readFile(bundle.filePath, 'utf8'));
  }
} finally {
  await workerFarm.end();
}
```

{% endsamplefile %}
{% endsample %}