packages/lit-dev-content/site/blog/2022-02-07-eleventy.md
The Lit team is pleased to announce an experimental preview release of
@lit-labs/eleventy-plugin-lit,
a new plugin for Eleventy that renders your Lit
components as static HTML during your Eleventy build, and lets you hydrate them
after your JavaScript loads.
As with all Lit Labs projects, this release should be considered experimental and incomplete. We'd love for you to try it out and leave feedback, but expect to find a few rough edges.
Check out the <a href="https://github.com/lit/lit/tree/main/packages/labs/eleventy-plugin-lit">roadmap</a> for a list of issues and missing features we're still working on.
</aside>Check it out now on GitHub and NPM, or read on to learn more about what it does, why you might want to use it, and how it works.
After you've added @lit-labs/eleventy-plugin-lit to your Eleventy config, then
whenever you write a custom element tag in a markdown or HTML file, the initial
state of that component's shadow DOM and styles will be rendered directly into
the static HTML.
For example, given a markdown file hello.md:
# Greetings
<demo-greeter name="World"></demo-greeter>
And a component definition js/demo-greeter.js:
import {LitElement, html, css} from 'lit';
class DemoGreeter extends LitElement {
static styles = css`
b { color: red; }
`;
static properties = {
name: {},
};
render() {
return html`Hello <b>${this.name}</b>!`;
}
}
customElements.define('demo-greeter', DemoGreeter);
Then Eleventy will produce an HTML file hello/index.html like this:
<h1>Greetings</h1>
<demo-greeter name="World">
<template shadowroot="open">
<style>
b { color: red; }
</style>
Hello <b>World</b>!
</template>
</demo-greeter>
This HTML allows the browser to paint the initial state of the component's DOM and styles, preserving all of the encapsulation boundaries of web components, even before a single line of JavaScript has downloaded!
Later, when the JavaScript definition of <demo-greeter> has finally loaded,
the statically rendered component is upgraded to its fully interactive
JavaScript implementation through a process called hydration.
Statically rendering components can be an effective method for reducing the time it takes between a page starting to load, and the content becoming visible. This is an important consideration that contributes to the responsiveness of your site, particularly for users with slower connections and devices.
By transmitting the initial state of your components as static HTML, the browser is able to paint the initial view much faster than it takes to download, parse, and evaluate the JavaScript implementations of those components.
For a deeper dive into the benefits of static rendering, check out Rendering on the Web, and for a discussion of how to measure this aspect of web performance, check out Largest Contentful Paint (LCP).
The plugin uses @lit-labs/ssr under the hood, which works by creating an
instance of each component in a lightweight browser-like environment within the
Eleventy Node process, and evaluating the element's template using a special
version of Lit's render function. This special render function behaves much
like the render function that Lit uses in the browser, except that it emits a
stream of strings instead of writing to the DOM, allowing it to be efficiently
written out as static HTML.
For more information about @lit-labs/ssr, check out its GitHub
repo. We'll be
expanding the documentation soon to help developers integrate @lit-labs/ssr
into more tools and frameworks!
When @lit-labs/ssr renders a component, it uses <template shadowroot> HTML
elements to represent the component's shadow DOM and styles. When the browser
HTML parser encounters a <template shadowroot>, it applies that template's
content as the shadow root of its parent element. This way, all of the DOM and
style encapsulation guarantees of web components are preserved.
As of February 2022, Chrome and Edge have native support for Declarative Shadow
DOM, but Firefox and Safari have not yet implemented it. A very small polyfill
is available for browsers that don't yet have support. Integrating the polyfill
into your site is
documented
in the @lit-labs/eleventy-plugin-lit README.
For more information about Declarative Shadow DOM, check out Declarative Shadow DOM.
While static rendering lets your components' initial paint happen as quickly as possible, the components won't yet be interactive, because their JavaScript implementations haven't loaded.
Hydration is the process where a statically rendered component is upgraded to its JavaScript implementation, becoming responsive and interactive.
Lit comes with automatic support for hydration via the special
@lit-labs/ssr-client/lit-element-hydrate-support.js module. As long as this module has been
loaded, Lit components will detect when they have been statically rendered, and
will adopt their existing shadow root.
Hydration with Lit is very efficient, because Lit knows that it doesn't need to re-render the existing shadow root when it upgrades. If data changes after hydration, then only the parts of the shadow root that changed will be updated.
Check out the
roadmap
for @lit-labs/eleventy-plugin-lit for some of the main features and fixes you
can expect to land over the coming months.
If you try out @lit-labs/eleventy-plugin-lit, let us know if you have any
suggestions or find any problems by starting a
discussion or filing an
issue.