- Stable
2.0.1
Toggle Menu
1.93s
29.05s
Bundle Added in v3.0.0
Contents
The Bundle plugin is a plain-text bundler unlocking minimal per-page or app-level bundles of CSS, JavaScript, or HTML to be included in your Eleventy project.
Makes it easy to implement Critical CSS, in-use-only CSS/JS bundles, SVG icon libraries, or secondary HTML content to load via XHR.
Why?
This project is a minimum-viable bundler and asset pipeline in Eleventy. It does not perform any transpilation or code manipulation. The code you put in is the code you get out (with configurable transforms if you’d like to modify the code).
For more larger, more complex use cases you may want to use a more full featured bundler like Vite, Parcel, Webpack, rollup, esbuild, or others. But do note that a full-featured bundler has a significant build performance cost, so take care to weigh the cost of using that style of bundler against whether or not this plugin has sufficient functionality for your use case—especially as the platform matures and we see diminishing returns on code transpilation (ES modules everywhere).
Usage
This plugin is added to Eleventy by default and requires no additional installation. However, the plugin does not include any default bundles. You must add these yourself via addBundle
.
export default function(eleventyConfig) {
eleventyConfig.addBundle("css");
};
module.exports = function(eleventyConfig) {
eleventyConfig.addBundle("css");
};
addBundle
does two things:
- Creates a new
css
universal shortcode for adding arbitrary code to this bundle. - Adds
"css"
as an eligible bundle in thegetBundle
andgetBundleFileUrl
shortcodes.
Full addBundle
options list
export default function(eleventyConfig) {
eleventyConfig.addBundle("css", {
// Folder (relative to output directory) files will write to
toFileDirectory: "bundle",
// File extension used for bundle file output, defaults to bundle name
outputFileExtension: "css",
// Name of shortcode for use in templates, defaults to bundle name
shortcodeName: "css",
// shortcodeName: false, // disable this feature.
// Modify bundle content
transforms: [],
// If two identical code blocks exist in non-default buckets, they’ll be hoisted to the first bucket in common.
hoist: true,
// In 11ty.js templates, having a named export of `bundle` will populate your bundles.
bundleExportKey: "bundle",
// bundleExportKey: false, // disable this feature.
});
};
module.exports = function(eleventyConfig) {
eleventyConfig.addBundle("css", {
// Folder (relative to output directory) files will write to
toFileDirectory: "bundle",
// File extension used for bundle file output, defaults to bundle name
outputFileExtension: "css",
// Name of shortcode for use in templates, defaults to bundle name
shortcodeName: "css",
// shortcodeName: false, // disable this feature.
// Modify bundle content
transforms: [],
// If two identical code blocks exist in non-default buckets, they’ll be hoisted to the first bucket in common.
hoist: true,
// In 11ty.js templates, having a named export of `bundle` will populate your bundles.
bundleExportKey: "bundle",
// bundleExportKey: false, // disable this feature.
});
};
You can read more about:
Examples
Add to a bundle
Consider this markdown (via liquid) template file:
# My Blog Post
This is some content, I am writing markup.
{% css %}
em { font-style: italic; }
{% endcss %}
## More Markdown
{% css %}
strong { font-weight: bold; }
{% endcss %}
Results in a removal of the bundle additions from the rendered output, like so:
<h1>My Blog Post</h1>
<p>This is some content, I am writing markup.</p>
<h2>More Markdown</h2>
Rendering Bundles
You can fetch the bundle content and output it directly on your page using the getBundle
shortcode.
<!-- Use this *anywhere*: a layout file, content template, etc -->
<style>{% getBundle "css" %}</style>
<!--
You can add more code to the bundle after calling
getBundle and it *will* be included.
-->
{% css %}
* { color: orange; }
{% endcss %}
Write a Bundle to the File System
Writes the bundle content to a content-hashed file location in your output directory and returns the URL to the file for use like this:
<link rel="stylesheet" href="{% getBundleFileUrl "css" %}">
Note that writing bundles to files will likely be a slower user-experience for empty-cache first time visitors but better cached in the browser for repeat-views (and across multiple pages, too).
Asset Bucketing
You can pass an additional string argument to your shortcode to add a sub-container (or bucket) for your code.
<!-- This goes into a `defer` bucket -->
{% css "defer" %}
em { font-style: italic; }
{% endcss %}
And to retrieve the code, you do the same with getBundle
and getBundleFileUrl
:
<!-- Retrieve the `defer` bucket code -->
<style>{% getBundle "css", "defer" %}</style>
<!-- Or: -->
<link rel="stylesheet" href="{% getBundleFileUrl 'css', 'defer' %}">
Critical CSS
export default function(eleventyConfig) {
eleventyConfig.addBundle("css");
};
module.exports = function(eleventyConfig) {
eleventyConfig.addBundle("css");
};
Now we’ll use asset bucketing to divide CSS between the default bucket and a defer bucket, loaded asynchronously.
<!-- … -->
<head>
<!-- Inlined critical styles -->
<style>{% getBundle "css" %}</style>
<!-- Non-critical styles -->
<link rel="stylesheet" href="{% getBundleFileUrl 'css', 'defer' %}" fetchpriority="low">
</head>
<body>
<!-- This goes into a `default` bucket -->
{% css %}/* Inline in the head, great with @font-face! */{% endcss %}
<!-- This goes into a `defer` bucket (the bucket can be any string value) -->
{% css "defer" %}/* Load me later */{% endcss %}
</body>
<!-- … -->
SVG Icon Library
export default function(eleventyConfig) {
eleventyConfig.addBundle("svg");
};
module.exports = function(eleventyConfig) {
eleventyConfig.addBundle("svg");
};
<svg width="0" height="0" aria-hidden="true" style="position: absolute;">
<defs>{% getBundle "svg" %}</defs>
</svg>
<!-- Add icons to the set from anywhere on the page -->
{% svg %}
<g id="icon-close"><path d="…" /></g>
{% endsvg %}
And now you can use `icon-close` in as many SVG instances as you’d like (without repeating the heftier SVG content).
<svg><use xlink:href="#icon-close"></use></svg>
<svg><use xlink:href="#icon-close"></use></svg>
<svg><use xlink:href="#icon-close"></use></svg>
<svg><use xlink:href="#icon-close"></use></svg>
React Helmet style <head>
additions
export default function(eleventyConfig) {
eleventyConfig.addBundle("html");
};
module.exports = function(eleventyConfig) {
eleventyConfig.addBundle("html");
};
<!-- … -->
<head>
{% getBundle "html", "head" %}
</head>
<body>
<!-- Add things to `<head>` from anywhere on the page -->
{% html "head" %}
<link href="https://v1.opengraph.11ty.dev" rel="preconnect" crossorigin>
{% endhtml %}
</body>
<!-- … -->
Postprocess the Bundle Output
import postcss from "postcss";
import postcssNested from "postcss-nested";
export default function(eleventyConfig) {
eleventyConfig.addBundle("css", {
transforms: [
async function(content) {
// type contains the bundle name.
let { type, page } = this;
let result = await postcss([postcssNested]).process(content, { from: page.inputPath, to: null });
return result.css;
}
]
});
};
const postcss = require("postcss");
const postcssNested = require("postcss-nested");
module.exports = function(eleventyConfig) {
eleventyConfig.addBundle("css", {
transforms: [
async function(content) {
// type contains the bundle name.
let { type, page } = this;
let result = await postcss([postcssNested]).process(content, { from: page.inputPath, to: null });
return result.css;
}
]
});
};
Using with WebC
Starting with Eleventy WebC v0.9.0 (tracked at #48) the WebC Bundler Mode now uses the Bundle plugin under the hood.
To add CSS to a bundle in WebC, you would use a <style>
element in a WebC page or component:
<style>/* This is bundled. */</style>
<style webc:keep>/* Do not bundle me—leave as is */</style>
To add JS to a page bundle in WebC, you would use a <script>
element in a WebC page or component:
<script>/* This is bundled. */</script>
<script webc:keep>/* Do not bundle me—leave as is */</script>
<style @raw="getBundle('css')">
and <script @raw="getBundle('js')">
both work as expected in WebC to fetch bundle content.