@kitschpatrol/eleventy-plugin-parcel v1.0.9
@kitschpatrol/eleventy-plugin-parcel
A plugin integrating the Parcel build tool and dev server with the Eleventy static site generator.
Overview
This plugin adds a Parcel bundling step to the Eleventy 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
Add the plugin to your Eleventy project:
$ npm install --save-dev @kitschpatrol/eleventy-plugin-parcelLoad the plugin in your
.eleventy.jsfile: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: falseoption when adding the plugin: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.
Create a
.parcelrcfile in your project's root including at least the following:{ "extends": "@parcel/config-default", "resolvers": ["@mischnic/parcel-resolver-root", "..."] }You must include this for absolute links to resolve correctly in the
outputsubfolder 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 --quietA normal Eleventy build will output your site with all Parcel optimizations enabled:
$ npx @11ty/eleventyConfiguration
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:
parcelOptionsObject passed to configure additional options as specified by Parcel's InitialParcelOptions type.
Defaults to:
{ 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
parcelOptionsobject in an effort to make your life more convenient:By default, Parcel's
modeoption 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/eleventygets"production". You can override this by passing an explicitmodestring to yourparcelOptions.The Plugin automatically uses your Eleventy project's
outputfolder to correctly prefix yourparcelOptions.entriesstring or array.Similarly, for release builds, Parcel's
defaultTargetOptions.distDirpath is automatically set to match Eleventy'soutput.tempFolderNameString with name of folder to stage the Parcel builds. Defaults to
.11ty-parcel-tempThere'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 aservebuild. It's recommended to add this path, along with.parcel-cacheto you.gitignore.useMiddlewareBoolean specifying whether to use the Parcel development server as middleware. Defaults to
true.middlewareOptionsObject passed to the middleware (if
useMiddleware: true) as specified by the http-proxy-middleware options type.
Parcel will also pull configuration from a .parcelrc 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:
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.
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 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. Vite 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 or Edge features
- The dom-diffing 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
shouldDisableCacheoption - Parcel is configured with
shouldAutoInstallenabled by default, which means it will automatically make changes to yourpackage.jsonas 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 Parcel plug-in default to your
package.jsonif needed - Unlike Parcel 1.x, Parcel 2.x does not bundle middleware functionality as part of its development server... Instead, the plugin establishes the middleware proxy via 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
- Rico Sta. Cruz's eleventy-parcel-demo
- Mark van Seventer's eleventy-parcel-boilerplate
- Chris D. Macrae's parceleventy
- Dusty Candland's 11ty-starter
Also:
- CloudSh blog post
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.htmlto accommodate sites with un-crawlable pages
Maintainers
Acknowledgments
This plugin is basically a port of Zach Leat's eleventy-plugin-vite from Vite to Parcel.
Contributing
Issues and pull requests are welcome.
License
MIT © Eric Mika