eleventy-plugin-smol-jsx-bundler
v1.2.9
Published
An eleventy bundler that works with jsx.
Maintainers
Readme
Eleventy Plugin Smol Jsx Bundler
A simple bundler for JSX projects (eg, react/preact and mdx) that mimics the behavior of Eleventy's built in bundler.
To quote Eleventy:
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.
The advantages of Smol Jsx Bundler are
- All of your Jsx files are pure clean javascript
- Which means they can be unit tested easily
- As well as provide greater extensibility
- Additional features, such as deduping
Installation
npm install --save eleventy-plugin-smol-jsx-bundler
Usage
First ensure the plugin is included in your eleventy config
import jsxBundle from 'eleventy-plugin-smol-jsx-bundler';
export default async (eleventyConfig) => {
eleventyConfig.addPlugin(jsxBundle);
};
And then begin using the bundler. The best way to showcase its abilities is to compare it with the default one provided by Eleventy.
Add to a bundle
import { bundle } from 'eleventy-plugin-smol-jsx-bundler';
# My Blog Post
{ bundle('css', 'strong { font-weight: bold; }') }
This is some content, I am writing markup.# My Blog Post
{% css %}
strong { font-weight: bold; }
{% endcss %}
This is some content, I am writing markup.And the following template
import { bundle } from 'eleventy-plugin-smol-jsx-bundler';
const Index = (props: {page: Page, content: any}) => {
bundle('css', 'em { font-style: italic; }');
return <html>
<Head />
<body>
{props.content}
</body>
</html>;
};
export const render = (props: {page: Page, content: any}) => {
return <Index page={props.page} content={content}>;
};{% css %}
em { font-style: italic; }
{% endcss %}
<!doctype html>
<html>
{% import "./head.njk" as body with context %}
<body>
{{ content | safe }}
</body>
</html>Results in the following being rendered:
<html>
<head></head>
<body>
<h1>My Blog Post</h1>
<p>This is some content, I am writing markup.</p>
</body>
</html>Rendering Bundles
You can fetch the bundle content and output it directly on your page using the getBundle methods.
import { getBundle } from 'eleventy-plugin-smol-jsx-bundler';
export const Head = (props: {page: Page}) => {
return <head>
<style>{getBundle('css')}</style>
</head>;
};<head>
<style>{% getBundle "css" %}</style>
</head>Results in the following being rendered:
<head>
<style>
em { font-style: italic; }
strong { font-weight: bold; }
</style>
</head>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.
import { getBundle } from 'eleventy-plugin-smol-jsx-bundler';
export const Head = (props: {page: Page}) => {
return <head>
<link
rel="stylesheet"
href={getBundleFile('css', /* extension */ 'css')}
/>
</head>;
};<head>
<link rel="stylesheet" href="{% getBundleFileUrl "css" %}">
</head>Postprocess the Bundle Output
It is possible to run a real bundler over the output from Smol Jsx Bundler
import jsxBundle from 'eleventy-plugin-smol-jsx-bundler';
import postcss from "postcss";
import postcssNested from "postcss-nested";
export default function(eleventyConfig) {
eleventyConfig.addPlugin(jsxBundle, {
transform: (name) => {
// 'css' is the "name" value you passed to `bundle` and `getBundle`.
if(name === 'css') {
return async function(content) {
const result = await postcss([postcssNested]).process(content);
return result.css;
}
}
// Use the default compiler, which copies the content verbatim.
return undefined;
}
});
};Further enhancements by Smol Jsx Bundler
Dedupe
If you write the same bundle content twice, the bundler will dedupe it. Furthermore, if you write the same bundle file twice, the bundler will dedupe it.
For example, say you have these three files.
import { bundle } from 'eleventy-plugin-smol-jsx-bundler';
# Welcome to my website!
{ bundle('css', 'strong { font-weight: bold; }') }
{ bundle('css', 'strong { font-weight: bold; }') }
Good stuff coming soon!
{ bundle('css', 'defer', '* { color: orange; }') }import { bundle } from 'eleventy-plugin-smol-jsx-bundler';
# My Blog Post
{ bundle('css', 'strong { font-weight: bold; }') }
This is some content, I am writing markup.
{ bundle('css', 'defer', 'div { color: green; line-height: 100px; }') }import { bundle } from 'eleventy-plugin-smol-jsx-bundler';
# About me
{ bundle('css', 'strong { font-weight: bold; }') }
{ bundle('css', 'div { width: 500px; }') }
I love Smol Jsx Bundler!
{ bundle('css', 'defer', '* { color: orange; }') }And this template
import { bundle, getBundle } from 'eleventy-plugin-smol-jsx-bundler';
const Index = (props: {page: Page, content: any}) => {
bundle('css', 'em { font-style: italic; }');
return <html>
<head>
<style>{getBundle('css')}</style>
<link
rel="stylesheet"
href={getBundleFile('css', 'defer', /* extension */ 'css')}
/>
<body>
{props.content}
</body>
</html>;
};
export const render = (props: {page: Page, content: any}) => {
return <Index page={props.page} content={content}>;
};Results in the following being rendered:
<html>
<head>
<style>
strong { font-weight: bold; }
em { font-style: italic; }
</style>
<link rel="stylesheet" href="/bundles/190027b58ff46f42b008001cfd0a09fc.css" />
</head>
<body>
<h1>Welcome to my website!</h1>
<p>Good stuff coming soon!</p>
</body>
</html><html>
<head>
<style>
strong { font-weight: bold; }
em { font-style: italic; }
</style>
<link rel="stylesheet" href="/bundles/7ca4648f38c73e8b116a4b0478944d6b.css" />
</head>
<body>
<h1>My Blog Post</h1>
<p>This is some content, I am writing markup.</p>
</body>
</html><html>
<head>
<style>
strong { font-weight: bold; }
em { font-style: italic; }
div { width: 500px; }
</style>
<link rel="stylesheet" href="/bundles/7ca4648f38c73e8b116a4b0478944d6b.css" />
</head>
<body>
<h1>About me</h1>
<p>I love Smol Jsx Bundler!</p>
</body>
</html>Using Smol Jsx Bundler as Jsx Components
If you prefer Jsx components, you can also use those.
import { Bundle, GetBundle } from 'eleventy-plugin-smol-jsx-bundler';
export const Foo = (props: {page: Page}) => {
return <div>
<Bundle name='css'>
* { color: orange; }
</Bundle>
</div>;
};
export const Bar = (props: {page: Page}) => {
return <style>
<GetBundle name='css'>
</style>;
};Using Smol Jsx Bundler during a test
Sometimes you need to install a fake JsxBundler during a test. Note this doesn't test the full functionality, just a facsimile.
import { expect } from 'chai';
import { bundle } from './bundles.js';
import { fakeJsxBundle, getFakeBundle, resetJsxBundle } from './plugin.fake.js';
describe('test', () => {
beforeEach(() => {
fakeJsxBundle();
});
afterEach(() => {
resetJsxBundle();
});
it('should get real content', () => {
bundle('test', 'content');
expect(getFakeBundle('test')).to.equal('content');
});
});