npm package: @kitschpatrol/eleventy-plugin-parcel
Description: A plugin integrating the Parcel build tool and dev server with the Eleventy static site generator.
Author: Eric Mika
Latest version: 1.0.10

<!--+ Warning: Content inside HTML comment blocks was generated by mdat and may be overwritten. +-->

<!-- title -->

# @kitschpatrol/eleventy-plugin-parcel

<!-- /title -->

<!-- badges -->

[![NPM Package @kitschpatrol/eleventy-plugin-parcel](https://img.shields.io/npm/v/@kitschpatrol/eleventy-plugin-parcel.svg)](https://npmjs.com/package/@kitschpatrol/eleventy-plugin-parcel)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

<!-- /badges -->

<!-- short-description -->

**A plugin integrating the Parcel build tool and dev server with the Eleventy static site generator.**

<!-- /short-description -->

## Overview

This plugin adds a [Parcel](https://parceljs.org) bundling step to the [Eleventy](https://www.11ty.dev) build process, and (optionally) allows the use of the Parcel Development Server as middleware during development.

Parcel is invoked automatically each time Eleventy finishes a build of your site, performing additional optimization and transpilation of various scripts and resources. Eleventy then launches its integrated development server to provide a preview of the site with automatic reloading when files are changed.

This post-processing step happens entirely within Eleventy's plugin system; no additions or modifications to your NPM scripts are required.

## Getting started

### Dependencies

This plugin is designed for Eleventy 2.x and Parcel 2.x. It is _not_ compatible with Eleventy 1.x. It has not yet been tested with Eleventy 3.x. Node 14+ is required.

The installation instrutions below assume you already have an Eleventy 2.x project that you want to add Parcel to.

### Installation

1. Add the plugin to your Eleventy project:

   ```
   $ npm install --save-dev @kitschpatrol/eleventy-plugin-parcel
   ```

2. Load the plugin in your `.eleventy.js` file:

   ```js
   const eleventyParcelPlugin = require("@kitschpatrol/eleventy-plugin-parcel");

   module.exports = function (eleventyConfig) {
     eleventyConfig.addPlugin(eleventyParcelPlugin);
   };
   ```

   Note that if you do _not_ want to use the Parcel Development Server as middleware when serving your site, pass the `useMiddleware: false` option when adding the plugin:

   ```js
   const eleventyParcelPlugin = require("@kitschpatrol/eleventy-plugin-parcel");

   module.exports = function (eleventyConfig) {
     eleventyConfig.addPlugin(eleventyParcelPlugin, { useMiddleware: false });
   };
   ```

   This serves your site as usual via an unmodified version of the Eleventy Dev Server, but Parcel will still process your output.

3. Create a [`.parcelrc`](https://github.com/parcel-bundler/parcel/blob/65500fbb07ff100c1fe5dd32e98fb80ff889f32e/packages/core/types/index.js#L55) file in your project's root including at least the following:

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

   _You must include this for absolute links to resolve correctly in the `output` subfolder when Parcel spiders through your site!_

## Usage

Build and run your Eleventy project as usual. The output from Eleventy will be passed to Parcel, which will process the site, replacing the contents of your `output` folder (usually `_site`), and then start the Eleventy Dev Server:

```
$ npx @11ty/eleventy --serve --quiet
```

A normal Eleventy build will output your site with all Parcel optimizations enabled:

```
$ npx @11ty/eleventy
```

## Configuration

Additional configuration may be passed to Parcel when the plugin is added to Eleventy's configuration.

The available top-level option keys are as follows:

- `parcelOptions`

  Object passed to configure additional options as specified by Parcel's [InitialParcelOptions type](https://parceljs.org/plugin-system/api/#InitialParcelOptions).

  Defaults to:

  ```js
  {
    parcelOptions: {
      entries: "index.html",
      defaultConfig: "@parcel/config-default",
      shouldDisableCache: true,
      shouldAutoInstall: true,
      serveOptions: {
        port: 3000,
      },
      hmrOptions: {
        port: 3001,
      }
    }
  }
  ```

  _Important notes about how the plugin dynamically modifies the `parcelOptions` object in an effort to make your life more convenient:_

  By default, Parcel's `mode` option is set dynamically based on the context of the build. Serve builds, e.g. `npx @11ty/eleventy --serve`, gets `"development"` mode, while release builds, e.g. `npx @11ty/eleventy` gets `"production"`. You can override this by passing an explicit `mode` string to your `parcelOptions`.

  The Plugin automatically uses your Eleventy project's `output` folder to correctly prefix your `parcelOptions.entries` string or array.

  Similarly, for release builds, Parcel's `defaultTargetOptions.distDir` path is automatically set to match Eleventy's `output`.

- `tempFolderName`

  String with name of folder to stage the Parcel builds. Defaults to `.11ty-parcel-temp` There's little reason to change this unless there is a conflict. This folder is automatically created and cleaned up during the release build process, but may linger during a `serve` build. It's recommended to add this path, along with `.parcel-cache` to you `.gitignore`.

- `useMiddleware`

  Boolean specifying whether to use the Parcel development server as middleware. Defaults to `true`.

- `middlewareOptions`

  Object passed to the middleware (if `useMiddleware: true`) as specified by the [http-proxy-middleware options type](https://github.com/chimurai/http-proxy-middleware#options).

Parcel will also pull configuration from a [`.parcelrc`](https://github.com/parcel-bundler/parcel/blob/65500fbb07ff100c1fe5dd32e98fb80ff889f32e/packages/core/types/index.js#L55) file in your project's root to further customize the build process.

### Examples

Here are a few example configurations to customize the Parcel's plugin's behavior. These object are passed to the plugin via the `addPlugin` method, usually in your projects `.eleventy.js` file.

#### Skip middleware

Skip the Parcel middleware and always build with all Parcel's optimizations enabled, regardless of invocation context:

```js
const eleventyParcelPlugin = require("@kitschpatrol/eleventy-plugin-parcel");

module.exports = function (eleventyConfig) {
  eleventyConfig.addPlugin(eleventyParcelPlugin, {
    parcelOptions: {
      mode: "production",
    },
    useMiddleware: false,
  });
};
```

#### Custom rewrite

Customize settings passed to `http-proxy-middleware` to rewrite paths in a way that allows you to drop the `.html` from URLs. This works well with the [parcel-optimizer-friendly-urls Parcel plugin](https://github.com/vseventer/parcel-optimizer-friendly-urls).

```js
const eleventyParcelPlugin = require("@kitschpatrol/eleventy-plugin-parcel");

module.exports = function (eleventyConfig) {
  eleventyConfig.addPlugin(eleventyParcelPlugin, {
    useMiddleware: true,
    middlewareOptions: {
      pathRewrite: {
        "^([^.]+?)$": "$1.html",
      },
    },
  });
};
```

## Background

### Motivation

Simplicity and a sense of containment are part Eleventy's charm, and there's a certain appeal to keeping the build process as "close to the core" as possible, even as a site's complexity accumulates. The very thorough [eleventy-high-performance-blog](https://github.com/google/eleventy-high-performance-blog) starter template illustrates this philosophy in practice.

For a while I've hewn to a similar approach in my own projects, but have found myself plumbing together byzantine chains of smaller tools to optimize images, add cache-busting hashes, generate CSP headers, etc. etc. — problems that have been solved several times over by a variety of build tools.

An official asset pipeline has been [a topic of discussion on Eleventy's issue pages over the years](https://github.com/11ty/eleventy/issues/272). [Vite](https://vitejs.dev) seems likely to be ordained as such, but Parcel has significant feature overlap — so I wanted to kick the tires on it as well as a point of comparison.

### Implementation notes

- Passthrough files must be copied to the output folder to be accessible to Parcel (the plugin sets `eleventyConfig.setServerPassthroughCopyBehavior("copy");`)
- Not tested with Eleventy's [Serverless](https://www.11ty.dev/docs/plugins/serverless/) or [Edge](https://www.11ty.dev/docs/plugins/edge/) features
- The dom-diffing [morphdom](https://github.com/patrick-steele-idem/morphdom) functionality integrated in the Eleventy Dev Server's auto-reloading logic does not play well with Parcel's output, and must be disabled (the plugin sets `eleventyConfig.setServerOptions({ domdiff: false });`)
- Parcel's caching system seems to have issues with Eleventy's output, and is disabled via the `shouldDisableCache` option
- Parcel is configured with `shouldAutoInstall` enabled by default, which means it will automatically make changes to your `package.json` as plugins are needed to handle various file types
- To avoid duplication of certain configuration parameters, the plugin writes an object related to the [parcel-resolver-root](https://github.com/mischnic/parcel-resolver-root) Parcel plug-in default to your `package.json` if needed
- Unlike Parcel 1.x, Parcel 2.x [does not bundle middleware functionality](https://github.com/parcel-bundler/parcel/discussions/4612) as part of its development server... Instead, the plugin establishes the middleware proxy via [http-proxy-middleware](https://github.com/chimurai/http-proxy-middleware)

### Similar projects

Many others have combined Parcel and Eleventy in various ways and at different points in the build chain:

- Michelle Barker's [eleventy-parcel](https://github.com/mbarker84/eleventy-parcel)
- Rico Sta. Cruz's [eleventy-parcel-demo](https://github.com/rstacruz/eleventy-parcel-demo)
- Mark van Seventer's [eleventy-parcel-boilerplate](https://github.com/vseventer/eleventy-parcel-boilerplate)
- Chris D. Macrae's [parceleventy](https://github.com/chrisdmacrae/parceleventy)
- Dusty Candland's [11ty-starter](https://github.com/candland/11ty-starter)

Also:

- CloudSh [blog post](https://cloudsh.com/eleventy/posts/2019/eleventy_and_parceljs_working_together.html)

## The future

- [ ] Eleventy 3.x testing and support
- [ ] Alternative to resolver dependency
- [ ] Pass resolver plugin options differently to avoid dynamically modifying `package.js`
- [ ] Support Parcel's cache (currently has issues with reloading)
- [ ] Legacy BrowserSync dev server reload timing issues
- [ ] More intelligent Parcel entry point than `index.html` to accommodate sites with un-crawlable pages

## Maintainers

[@kitschpatrol](https://github.com/kitschpatrol)

## Acknowledgments

This plugin is basically a port of Zach Leat's [eleventy-plugin-vite](https://github.com/11ty/eleventy-plugin-vite) from Vite to Parcel.

<!-- footer -->

## Contributing

[Issues](https://github.com/kitschpatrol/eleventy-plugin-parcel/issues) and pull requests are welcome.

## License

[MIT](license.txt) © Eric Mika

<!-- /footer -->