Lit Blog Latest news, announcements, and highlights from the Lit team and community. https://lit.dev/blog/ https://lit.dev/images/icon.svg https://lit.dev/images/logo.svg https://lit.dev/images/icon.svg https://lit.dev/images/logo.svg 2025-10-14T00:00:00Z Lightning-fast templates & Web Components: lit-html & LitElement 2019-02-05T00:00:00Z https://lit.dev/blog/2019-02-05-lit-element-and-lit-html-release/ Announcing the stable releases of our next-generation web development libraries. Justin Fagnani https://twitter.com/justinfagnani <p>Today we're excited to announce the first stable releases of our two next-generation web development libraries: <a href="https://lit-html.polymer-project.org/">lit-html</a> and <a href="https://lit-element.polymer-project.org/">LitElement</a>.</p> <p>lit-html is a tiny, fast, expressive library for HTML templating. LitElement is a simple base class for creating Web Components with lit-html templates.</p> <p>If you've been following the projects, you probably know what lit-html and LitElement are all about (and you can <a href="https://lit.dev/blog/2019-02-05-lit-element-and-lit-html-release/#get-started">skip to the end</a> if you like). If you're new to lit-html and LitElement, read on for an overview.</p> <div class="heading h2"> <h2 id="lit-html:-a-tiny-fast-library-for-html-templating" tabindex="-1">lit-html: a tiny, fast library for HTML templating</h2> </div> <p>lit-html is a tiny (just over 3k bundled, minified, and gzipped) and fast JavaScript library for HTML templating. lit-html works well with functional programming approaches, letting you express your application's UI declaratively, as a function of its state.</p> <pre><code class="language-js"><figure class="cm-editor"><div class="cm-line"><span class="tok-keyword">const</span> <span class="tok-variableName tok-definition">myTemplate</span> <span class="tok-operator">=</span> <span class="tok-punctuation">(</span><span class="tok-variableName tok-definition">name</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">=&gt;</span> <span class="tok-variableName">html</span>`</div><div class="cm-line"> <span class="tok-punctuation">&lt;</span><span class="tok-typeName">div</span><span class="tok-punctuation">&gt;</span></div><div class="cm-line"> Hi, my name is <span class="tok-punctuation">${</span><span class="tok-variableName">name</span><span class="tok-punctuation">}</span>.</div><div class="cm-line"> <span class="tok-punctuation">&lt;/</span><span class="tok-typeName">div</span><span class="tok-punctuation">&gt;</span></div><div class="cm-line">`<span class="tok-punctuation">;</span></div></figure></code></pre> <p>It's simple to render a lit-html template:</p> <pre><code class="language-js"><figure class="cm-editor"><div class="cm-line"><span class="tok-variableName">render</span><span class="tok-punctuation">(</span><span class="tok-variableName">myTemplate</span><span class="tok-punctuation">(</span><span class="tok-string">'Ada'</span><span class="tok-punctuation">)</span><span class="tok-punctuation">,</span> <span class="tok-variableName">document</span><span class="tok-operator">.</span><span class="tok-propertyName">body</span><span class="tok-punctuation">)</span><span class="tok-punctuation">;</span></div></figure></code></pre> <p>Re-rendering a template only updates the data that's changed:</p> <pre><code class="language-js"><figure class="cm-editor"><div class="cm-line"><span class="tok-variableName">render</span><span class="tok-punctuation">(</span><span class="tok-variableName">myTemplate</span><span class="tok-punctuation">(</span><span class="tok-string">'Grace'</span><span class="tok-punctuation">)</span><span class="tok-punctuation">,</span> <span class="tok-variableName">document</span><span class="tok-operator">.</span><span class="tok-propertyName">body</span><span class="tok-punctuation">)</span><span class="tok-punctuation">;</span></div></figure></code></pre> <p>lit-html is efficient, expressive, and extensible:</p> <ul> <li> <p><strong>Efficient</strong>. lit-html is lightning fast. When data changes, lit-html doesn't need to do any diffing; instead, it remembers where you inserted expressions in your template and only updates these dynamic parts.</p> </li> <li> <p><strong>Expressive</strong>. lit-html gives you the full power of JavaScript, declarative UI, and functional programming patterns. The expressions in a lit-html template are just JavaScript, so you don't need to learn a custom syntax and you have all the expressiveness of the language at your disposal. lit-html supports many kinds of values natively: strings, DOM nodes, arrays and more. Templates themselves are values that can be computed, passed to and from functions, and nested.</p> </li> <li> <p><strong>Extensible</strong>: lit-html is also customizable and extensible—your very own template construction kit. Directives customize how values are handled, allowing for asynchronous values, efficient keyed-repeats, error boundaries, and more. lit-html includes several ready-to-use directives and makes it easy to define your own.</p> </li> </ul> <p>A number of libraries and projects have already incorporated lit-html. You can find a list of some of these libraries in the <a href="https://github.com/web-padawan/awesome-lit-html">awesome-lit-html</a> repo on GitHub.</p> <p>If templating is all you need, you can get started now with the <a href="https://lit-html.polymer-project.org/">lit-html docs</a>. If you'd like to build components to use in your app or share with your team, read on to learn more.</p> <div class="heading h2"> <h2 id="litelement:-a-lightweight-web-component-base-class" tabindex="-1">LitElement: a lightweight Web Component base class</h2> </div> <p>LitElement is a lightweight base class that makes it easier than ever to build and share Web Components.</p> <p>LitElement uses lit-html to render components and adds APIs to declare reactive properties and attributes. Elements update automatically when their properties change. And they update <em>fast</em>, without diffing.</p> <p>Here's a simple LitElement component:</p> <litdev-switchable-sample> <pre><code class="language-ts"><figure class="cm-editor"><div class="cm-line"><span class="tok-meta">@</span><span class="tok-variableName">customElement</span><span class="tok-punctuation">(</span><span class="tok-string">'name-tag'</span><span class="tok-punctuation">)</span></div><div class="cm-line"><span class="tok-keyword">class</span> <span class="tok-className">NameTag</span> <span class="tok-keyword">extends</span> <span class="tok-variableName">LitElement</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-meta">@</span><span class="tok-variableName">property</span><span class="tok-punctuation">(</span><span class="tok-punctuation">)</span></div><div class="cm-line"> <span class="tok-propertyName tok-definition">name</span> <span class="tok-operator">=</span> <span class="tok-string">'a secret'</span><span class="tok-punctuation">;</span></div><div class="cm-line"><br /></div><div class="cm-line"> <span class="tok-propertyName tok-definition">render</span><span class="tok-punctuation">(</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-keyword">return</span> <span class="tok-variableName">html</span>`<span class="tok-punctuation">&lt;</span><span class="tok-typeName">p</span><span class="tok-punctuation">&gt;</span>Hi, my name is <span class="tok-punctuation">${</span><span class="tok-keyword">this</span><span class="tok-operator">.</span><span class="tok-propertyName">name</span><span class="tok-punctuation">}</span>!<span class="tok-punctuation">&lt;/</span><span class="tok-typeName">p</span><span class="tok-punctuation">&gt;</span>`<span class="tok-punctuation">;</span></div><div class="cm-line"> <span class="tok-punctuation">}</span></div><div class="cm-line"><span class="tok-punctuation">}</span></div></figure></code></pre> <pre><code class="language-js"><figure class="cm-editor"><div class="cm-line"><span class="tok-keyword">class</span> <span class="tok-className">NameTag</span> <span class="tok-keyword">extends</span> <span class="tok-variableName">LitElement</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-keyword">static</span> <span class="tok-propertyName tok-definition">properties</span> <span class="tok-operator">=</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-propertyName tok-definition">name</span><span class="tok-punctuation">:</span> <span class="tok-punctuation">{</span><span class="tok-punctuation">}</span><span class="tok-punctuation">,</span></div><div class="cm-line"> <span class="tok-punctuation">}</span><span class="tok-punctuation">;</span></div><div class="cm-line"><br /></div><div class="cm-line"> <span class="tok-propertyName tok-definition">constructor</span><span class="tok-punctuation">(</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-atom">super</span><span class="tok-punctuation">(</span><span class="tok-punctuation">)</span><span class="tok-punctuation">;</span></div><div class="cm-line"> <span class="tok-keyword">this</span><span class="tok-operator">.</span><span class="tok-propertyName">name</span> <span class="tok-operator">=</span> <span class="tok-string">'a secret'</span><span class="tok-punctuation">;</span></div><div class="cm-line"> <span class="tok-punctuation">}</span></div><div class="cm-line"><br /></div><div class="cm-line"> <span class="tok-propertyName tok-definition">render</span><span class="tok-punctuation">(</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-keyword">return</span> <span class="tok-variableName">html</span>`<span class="tok-punctuation">&lt;</span><span class="tok-typeName">p</span><span class="tok-punctuation">&gt;</span>Hi, my name is <span class="tok-punctuation">${</span><span class="tok-keyword">this</span><span class="tok-operator">.</span><span class="tok-propertyName">name</span><span class="tok-punctuation">}</span>!<span class="tok-punctuation">&lt;/</span><span class="tok-typeName">p</span><span class="tok-punctuation">&gt;</span>`<span class="tok-punctuation">;</span></div><div class="cm-line"> <span class="tok-punctuation">}</span></div><div class="cm-line"><span class="tok-punctuation">}</span></div><div class="cm-line"><span class="tok-variableName">customElements</span><span class="tok-operator">.</span><span class="tok-propertyName">define</span><span class="tok-punctuation">(</span><span class="tok-string">'name-tag'</span><span class="tok-punctuation">,</span> <span class="tok-variableName">NameTag</span><span class="tok-punctuation">)</span><span class="tok-punctuation">;</span></div></figure></code></pre> </litdev-switchable-sample> <p>This creates an element you can use anywhere you'd use a regular HTML element:</p> <pre><code class="language-html"><figure class="cm-editor"><div class="cm-line"><span class="tok-punctuation">&lt;</span><span class="tok-typeName">name-tag</span> <span class="tok-propertyName">name</span><span class="tok-operator">=</span><span class="tok-string">"Ida"</span><span class="tok-punctuation">&gt;</span><span class="tok-punctuation">&lt;/</span><span class="tok-typeName">name-tag</span><span class="tok-punctuation">&gt;</span></div></figure></code></pre> <p>If you use Web Components already, you'll be happy to hear that they're now natively supported in Chrome, Safari and Firefox. Edge support is coming soon, and polyfills are only needed for legacy browser versions.</p> <p>If you're new to Web Components, you should give them a try! Web Components let you extend HTML in a way that interoperates with other libraries, tools, and frameworks. This makes them ideal for sharing UI elements within a large organization, publishing components for use anywhere on the web, or building UI design systems like Material Design.</p> <p>You can use custom elements anywhere you use HTML: in your main document, in a CMS, in Markdown, or in views <a href="https://custom-elements-everywhere.com/">built with frameworks</a> like React and Vue. You can also mix and match LitElement components with other Web Components, whether they've been written using vanilla web technologies or made with the help of tools like <a href="https://developer.salesforce.com/blogs/2018/12/introducing-lightning-web-components.html">Salesforce Lightning Web Components</a>, Ionic's <a href="https://stenciljs.com/">Stencil</a>, <a href="https://skatejs.netlify.com/">SkateJS</a> or the <a href="https://polymer-library.polymer-project.org/">Polymer library</a>.</p> <div class="heading h2"> <h2 id="get-started" tabindex="-1">Get started</h2> </div> <p>Want to try lit-html and LitElement? A good starting point is the LitElement tutorial:</p> <ul> <li><a href="https://lit-element.polymer-project.org/try">Try LitElement</a></li> </ul> <p>If you're interested in using lit-html by itself, or integrating lit-html templating into another project, see the lit-html docs:</p> <ul> <li><a href="https://lit-html.polymer-project.org/">lit-html docs</a></li> </ul> <p>As always, let us know what you think. You can reach us on <a href="https://lit.dev/discord/">Discord</a> or <a href="https://twitter.com/buildWithLit">Twitter</a>. Our projects are open source (of course!) and you can report bugs, file feature requests or suggest improvements on GitHub:</p> <ul> <li><a href="https://github.com/lit/lit">lit-html on GitHub</a></li> <li><a href="https://github.com/Polymer/lit-element">LitElement on GitHub</a></li> </ul> LitElement 3.0 & lit-html 2.0: Early Preview Release 2020-09-22T00:00:00Z https://lit.dev/blog/2020-09-22-lit-element-and-lit-html-next-preview/ Preview the next major versions of LitElement and lit-html. <p>Today we’re publishing the first preview releases of the next major versions of our flagship libraries, LitElement and lit-html.</p> <p>These releases include most of the breaking changes we intend to make, and most of the functionality we want to carry over from the previous versions. They are not yet feature complete or fully API stable. Notably, they don’t yet support legacy browsers like IE11, or browsers requiring the web components polyfill.</p> <div class="heading h2"> <h2 id="motivation" tabindex="-1">Motivation</h2> </div> <p>We’ve been very happy with the current versions of our libraries—they’re fast, small, and stable (yay!)—and in some ways we don’t have very many pressing needs to make breaking changes. We don’t make breaking changes lightly. But there are some compelling reasons for changes that we think will improve the user-experience of components and applications built with LitElement.</p> <ol> <li> <p><strong>Performance</strong></p> <p>We have found that some of our browser-bug workaround code and customization abstractions prevent optimizations that we would like to do.</p> </li> <li> <p><strong>Size</strong></p> <p>That same code, and our extensive public API, costs bytes. We always want to find ways to make the libraries smaller.</p> </li> <li> <p><strong>Features &amp; API cleanup</strong></p> <p>Some features are difficult to add in a cost-effective way with the current architecture, or can’t really be improved without breaking changes.</p> </li> <li> <p><strong>Server-side-rendering</strong></p> <p>lit-html has an extremely flexible and customizable API, and in some ways is more of a template-system construction kit than a single template-system. But this flexibility complicates SSR, which needs to make assumptions about how the server-rendered HTML maps to templates. SSR would only work well with the default, uncustomized lit-html, so limiting customization makes SSR more reliable. Very few developers used the customization APIs anyway.</p> </li> </ol> <p>We also want to make the directive API SSR compatible by limiting access to the DOM.</p> <div class="heading h2"> <h2 id="what's-changed" tabindex="-1">What’s changed</h2> </div> <p>These are new major versions, so there are some breaking changes, but we want to minimize disruption to our users as much as possible. We’ve limited the breaking changes so that they don’t affect most users, or only require a mechanical change (like changing an import).</p> <p>Please see the READMEs (<a href="https://github.com/lit/lit/tree/lit-next/packages/lit-element#readme">LitElement</a>, <a href="https://github.com/lit/lit/tree/lit-next/packages/lit-html#readme">lit-html</a>) and CHANGELOGs (<a href="https://github.com/lit/lit/blob/lit-next/packages/lit-element/CHANGELOG.md">LitElement</a>, <a href="https://github.com/lit/lit/blob/lit-next/packages/lit-html/CHANGELOG.md">lit-html</a>) for the most detailed list of changes.</p> <p>The most important changes:</p> <ul> <li> <p>Customizing the syntax of lit-html is no longer directly supported. The templateFactory and TemplateProcessor APIs have been removed.</p> </li> <li> <p>The public API has been minimized in order to facilitate better minification and future evolution.</p> </li> <li> <p>The lit-html directive API has changed to be class-based and to persist directive instances. Directives should be easier to write and easier to make SSR compatible.</p> </li> <li> <p>The LitElement decorators are no longer exported from the main module—they have to be imported individually or from a new <code>lit-element/decorators.js</code> module. This means smaller app sizes for non-decorator-users and opens the door to new decorators implementing the current TC39 JavaScript proposal when those arrive.</p> </li> <li> <p>lit-html no longer uses <code>instanceof</code> or module-level WeakMaps to detect special objects like template results and directives, which should improve the compatibility of multiple copies of lit-html in a single app. We still recommend de-duping npm packages, but more cases will work now.</p> </li> <li> <p>Safari 12 has a critical <a href="https://bugs.webkit.org/show_bug.cgi?id=190756">template literal bug</a>, which is no longer worked around in lit-html. If you support Safari 12 you will have to compile template literals to their ES5 equivalent. Note that babel-preset-env already does this for the broken versions of Safari.</p> </li> </ul> <p>There are smaller changes listed in the change logs. Overall we hope these versions are drop in replacements for most users, or only require updating decorator imports.</p> <div class="heading h2"> <h2 id="installation" tabindex="-1">Installation</h2> </div> <p>Run:</p> <pre><code class="language-sh"><figure class="cm-editor"><div class="cm-line">npm i lit-element@next-major</div></figure></code></pre> <p>And/or:</p> <pre><code class="language-sh"><figure class="cm-editor"><div class="cm-line">npm i lit-html@next-major</div></figure></code></pre> <div class="heading h2"> <h2 id="submitting-feedback" tabindex="-1">Submitting feedback</h2> </div> <p>We’re in the process of moving the next versions of LitElement and lit-html into a mono-repo. Please file issues on the <a href="https://github.com/lit/lit/issues">current lit-html repo</a>, using a prefix of <code>[lit-html]</code> or <code>[lit-element]</code>. We expect that, as with any pre-release, there will be common issues we will have to fix. Please search for your issue first. Issues for the next major versions will have the label lit-next.</p> <div class="heading h2"> <h2 id="what's-next" tabindex="-1">What’s next</h2> </div> <p>For the next preview release we will be focusing on browser and polyfill support, especially IE11.</p> Lit 2.0: Meet Lit, all over again! 2021-04-21T00:00:00Z https://lit.dev/blog/2021-04-21-lit-2.0-meet-lit-all-over-again/ New name, new site, new version: smaller, better, faster, and SSR-ready. Gray Norton https://twitter.com/graynorton <p>Today, we’re excited to announce the first release candidate of Lit 2.0!</p> <p>As we shared <a href="https://github.com/lit/lit/issues/1182">last</a> <a href="https://github.com/Polymer/lit-element/issues/1077">summer</a>, we have been hard at work on our first major update since shipping production-ready versions of lit-html and LitElement in early 2019. We’re calling this update Lit 2.0.</p> <p>The API has been stable for a few months, and we’ve gotten great feedback from prerelease users, so late last night we cut our first release candidate. All that stands between us and an official release is a bit more time for developers to put the software through its paces and identify any final issues.</p> <div class="heading h2"> <h2 id="what's-in-the-new-version" tabindex="-1">What’s in the new version?</h2> </div> <p>Our major goals for Lit 2.0 were to reduce size, add powerful new features, improve performance and make some key changes under the hood to facilitate server-side rendering (SSR) — all while minimizing breaking changes. Easy, right?</p> <p>Happily, we might have actually done it! To paraphrase a popular dance track from the early days of the Web, Lit 2.0 is:</p> <ul> <li> <p><strong>Smaller.</strong> Lit 2.0’s templating system weighs in at 2.8k (minified and compressed), 10% smaller than the previous version, and its complete component base class (including templating) is just 5.2k, 20% smaller than before.</p> </li> <li> <p><strong>Better.</strong> Meanwhile, we’ve added a raft of new features, including several templating enhancements; a clean, new, class-based API for directive authors; and reactive controllers, a powerful new primitive for sharing stateful logic between components.</p> </li> <li> <p><strong>Faster.</strong> Efficient rendering has always been one of our core values, and Lit 2.0 is speedier than ever before: up to 20% faster on initial render, and up to 15% faster on updates.</p> </li> <li> <p><strong>Server.</strong> Lit 2.0 includes the foundation for fast, streaming SSR and flexible client-side hydration, unlocking a full range of use cases — from integration with popular frameworks (e.g., Next.js) and static site generators (e.g., eleventy) to apps built entirely with Lit and other web components.</p> </li> </ul> <p>And all of these improvements come with minimal changes to the existing API: the vast majority of existing Lit code will run with little to no modification. If you’re updating from a previous version, check out our helpful <a href="https://lit.dev/docs/releases/upgrade/">upgrade guide</a>.</p> <div class="heading h2"> <h2 id="what-else-is-new" tabindex="-1">What else is new?</h2> </div> <p>As we hinted above, the big news doesn’t end with the Lit 2.0 update — we’ve also made some major improvements beyond the software itself.</p> <p>Most importantly, we’ve simplified our packaging, docs and presence. Whereas lit-html and LitElement have historically been separate packages with separate sites and docs, we’ve now combined them into a single product with a clear, simple identity — Lit — and a distinctive new logo.</p> <p>Users have casually referred to our offerings as “Lit” for some time. By formalizing this name and simplifying the way we deliver the software, we aim to make Lit even easier to understand and use.</p> <p>So, what does this mean in practice?</p> <ul> <li> <p><strong>A new npm package:</strong> Installing Lit is now as simple as typing <code>npm i lit</code>. Since this is really our second major release, we chose to release the initial version of the new package as 2.0.</p> </li> <li> <p><strong>A new website:</strong> <a href="https://lit.dev/">lit.dev</a> is a brand new, one-stop shop for all things Lit, with a complete set of unified docs, a no-install interactive tutorial, a playground for exploring and creating sample code, and a dedicated Lit blog.</p> </li> <li> <p><strong>A new home on GitHub:</strong> We’ve moved our source code and issue tracker to the new <a href="https://github.com/lit/lit">Lit org</a> on GitHub. Most of the code lives in the new lit mono-repo, which simplifies testing and releasing and makes the project more approachable for external contributors.</p> </li> <li> <p><strong>A new Twitter handle:</strong> We’ll be tweeting about Lit from <a href="https://twitter.com/buildWithLit">@buildWithLit</a> — follow this account to stay on top of all the latest news.</p> </li> </ul> <div class="heading h2"> <h2 id="simple.-fast.-web-components." tabindex="-1">Simple. Fast. Web Components.</h2> </div> <p>There’s actually a whole lot more to share, so we encourage you to explore lit.dev, watch today’s <a href="https://www.youtube.com/watch?v=f1j7b696L-E">launch event</a> (live or after the fact), and keep your eye on Twitter and the blog for more details in the coming weeks.</p> <p>But despite all the news, Lit fundamentally remains what it has always been: a simple library for building fast, lightweight web components. Because it embraces the browser’s native component model, Lit is perfectly suited for building shareable components or design systems, and it can also help you build highly maintainable, future-ready sites and apps.</p> <p>We can’t wait to see what you build with Lit 2.0!</p> Announcing Lit 2 stable release 2021-09-21T00:00:00Z https://lit.dev/blog/2021-09-21-announcing-lit-2/ Lit 2: smaller, better, faster, SSR-ready, and ready for production. <p>Today we're announcing the stable release of Lit 2. Lit 2 is a major update: it's smaller, faster and better than before, it lays the foundation for server-side rendering, and it's all wrapped up in the new <code>lit</code> package on npm.</p> <p>Lit has come a long way since April when we <a href="https://lit.dev/blog/2021-04-21-lit-2.0-meet-lit-all-over-again/">announced</a> the first release candidate for Lit 2. Since then, many partners have tested the release candidates on big applications and reported easy upgrades, better performance, and smaller bundles. In addition, some partners and community members have been exploring new features like reactive controllers and experimental server-side rendering support.</p> <p>Meanwhile, at Google, we've extensively tested Lit 2 by upgrading thousands of Google's internal components to the new version.</p> <p>Today we're happy to announce that Lit 2 is ready to go.</p> <p><strong>Correction:</strong> <em>The lit-analyzer CLI and VS Code Lit plugin are being updated to work with Lit 2. The original version of this post incorrectly stated that these had already been released.</em></p> <div class="heading h2"> <h2 id="what's-in-lit-2" tabindex="-1">What’s in Lit 2?</h2> </div> <p>Lit 2 adds a number of new features and enhancements while maintaining backward compatibility; in most cases, Lit 2 should be a drop-in replacement for previous versions. Significant new features in Lit 2 include:</p> <ul> <li> <p><strong>New directive API</strong>. Lit 2 introduces a new class-based API for writing <a href="https://lit.dev/docs/templates/custom-directives/">custom directives</a>, objects that can customize how Lit renders. Directives aren't new, but the new API makes them more powerful and easier to define.</p> </li> <li> <p><strong>Asynchronous directives</strong>. Async directives can be notified when they are added to and removed from the DOM, which allows directives to do clean up work. For example, an async directive could use the callbacks to subscribe and unsubscribe to an observable.</p> </li> <li> <p><strong>Reactive controllers</strong>. A <a href="https://lit.dev/docs/composition/controllers/">reactive controller</a> is an object that can hook into a component's <a href="https://lit.dev/docs/components/lifecycle/">lifecycle</a>, so they can respond when the component updates, and when the component is added to or removed from the DOM. Controllers can bundle state and behavior related to a feature, making it reusable across multiple component definitions. Reactive controllers can make it easy to add state management, animations, async tasks and much more to components.</p> </li> <li> <p><strong>Element expressions</strong>. New in Lit 2 is the ability to add expressions that act on an element as a whole, rather than modifying a property, attribute, or the element's children. <a href="https://lit.dev/docs/templates/expressions/#element-expressions">Element expressions</a> are useful for directives that need to manipulate multiple properties or to call methods on the element.</p> <p>For example, an experimental animation package, <code>@lit-labs/motion</code> provides an <code>animate()</code> directive that animates when the element's state changes. For example, the following snippet animates list items when the list reorders.</p> <pre><code class="language-js"><figure class="cm-editor"><div class="cm-line"><span class="tok-variableName">html</span>`</div><div class="cm-line"> <span class="tok-punctuation">${</span><span class="tok-variableName">repeat</span><span class="tok-punctuation">(</span><span class="tok-variableName">items</span><span class="tok-punctuation">,</span></div><div class="cm-line"> <span class="tok-punctuation">(</span><span class="tok-variableName tok-definition">item</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">=&gt;</span> <span class="tok-variableName">item</span><span class="tok-operator">.</span><span class="tok-propertyName">id</span><span class="tok-punctuation">,</span></div><div class="cm-line"> <span class="tok-punctuation">(</span><span class="tok-variableName tok-definition">item</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">=&gt;</span> <span class="tok-variableName">html</span>`<span class="tok-punctuation">&lt;</span><span class="tok-typeName">div</span> <span class="tok-punctuation">${</span><span class="tok-variableName">animate</span><span class="tok-punctuation">(</span><span class="tok-punctuation">)</span><span class="tok-punctuation">}</span><span class="tok-punctuation">&gt;</span><span class="tok-punctuation">${</span><span class="tok-variableName">item</span><span class="tok-punctuation">}</span><span class="tok-punctuation">&lt;/</span><span class="tok-typeName">div</span><span class="tok-punctuation">&gt;</span>`<span class="tok-punctuation">)</span></div><div class="cm-line"> <span class="tok-punctuation">}</span>`</div></figure></code></pre> <p>For a more complete example of the <code>animate</code> directive, see the package <a href="https://github.com/lit/lit/blob/main/packages/labs/motion/README.md">README</a>.</p> </li> <li> <p><strong>Static expressions</strong>. Also new in Lit 2, <a href="https://lit.dev/docs/templates/expressions/#static-expressions">static expressions</a> allow you to interpolate constant or rarely-changed values into a template before processing. Static expressions can be used in a variety of places where ordinary expressions cannot—for example, in tag-name position:</p> <pre><code class="language-js"><figure class="cm-editor"><div class="cm-line"><span class="tok-keyword">const</span> <span class="tok-variableName tok-definition">tagName</span> <span class="tok-operator">=</span> <span class="tok-variableName">literal</span><span class="tok-string2">`button`</span><span class="tok-punctuation">;</span></div><div class="cm-line"><span class="tok-variableName">html</span>`&lt;<span class="tok-punctuation">${</span><span class="tok-variableName">tagName</span><span class="tok-punctuation">}</span>&gt;&lt;/<span class="tok-punctuation">${</span><span class="tok-variableName">tagName</span><span class="tok-punctuation">}</span>&gt;`</div></figure></code></pre> </li> <li> <p><strong>SSR-ready</strong>. Lit 2 was rebuilt to be SSR-ready. The new <code>@lit-labs/ssr</code> package implements fast, streaming SSR for Lit on Node.js. SSR support is still experimental; work is ongoing to finish and test the SSR library.</p> </li> </ul> <p>In addition to the new features in the Lit library, we've made a few more changes around Lit:</p> <ul> <li> <p>All Lit related projects are in a <a href="https://github.com/lit/">new GitHub organization</a>. Most Lit related code has been moved to a monorepo to make it easier to test changes.</p> </li> <li> <p>The monorepo also includes a number of experimental projects, including <a href="https://www.npmjs.com/package/@lit-labs/ssr">server-side rendering</a> support for Lit and other web components; <a href="https://www.npmjs.com/package/@lit-labs/motion">animation helpers</a>; and a Lit controller for <a href="https://www.npmjs.com/package/@lit-labs/task">asynchronous tasks</a>. Experimental projects are published under the <code>@lit-labs</code> npm scope.</p> </li> <li> <p>An all-new website, <a href="https://lit.dev/">lit.dev</a>, featuring guides, API docs, tutorials, and an interactive code editor. We launched the site with the initial Lit release candidate; since then we've added two of the most-requested features: site search, and better support for JavaScript users, with switchable JavaScript/TypeScript code snippets.</p> </li> </ul> <div class="heading h2"> <h2 id="changes-since-rc-1" tabindex="-1">Changes since RC 1</h2> </div> <p>Since the initial RC, most changes have been bug fixes. A few notable changes:</p> <ul> <li> <p>Element lifecycle not paused when an element is disconnected. This reverts a change in Lit that caused some subtle bugs. If you developed an asynchronous directive using one of the Lit 2 release candidates, you may need to make some changes. For details, see <a href="https://github.com/lit/lit/pull/2034">PR #2034</a>.</p> </li> <li> <p>Better runtime warnings in the development build. For information on using the development build, see <a href="https://lit.dev/docs/tools/development/#development-and-production-builds">Development and production builds</a>.</p> </li> </ul> <p>For a full list of changes, see the <a href="https://github.com/lit/lit/blob/main/packages/lit/CHANGELOG.md">changelog</a>.</p> <div class="heading h2"> <h2 id="get-started-with-lit-2" tabindex="-1">Get started with Lit 2</h2> </div> <p>Want to try out Lit 2? Visit <a href="https://lit.dev/docs/getting-started/">lit.dev</a> to get started. The site features a <a href="https://lit.dev/tutorials">catalog of interactive tutorials</a> to get you started with Lit 2, an interactive <a href="https://lit.dev/playground/">playground</a> for live coding, guides, and API docs.</p> <p>Want to talk Lit? Join the <a href="https://lit.dev/discord/">Lit Discord</a> for discussions on Lit and web components, or open a discussion on our <a href="https://github.com/lit/lit/discussions">GitHub Discussions</a> board.</p> Watch the Lit 2 release livestream 2021-09-22T00:00:00Z https://lit.dev/blog/2021-09-22-lit-2-release-livestream/ What's new in Lit 2, a big-picture view of Lit usage at Google, and a community panel discussion. <p>If you weren't able to join us for the Lit 2 release livestream, you can watch the recording on YouTube.</p> <iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/nfb779XIhsU" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe> Lit 2.1 Release 2022-01-05T00:00:00Z https://lit.dev/blog/2022-01-05-lit-2.1-release/ New directives, new decorator, new observers package, and task/SSR updates Justin Fagnani https://twitter.com/justinfagnani Arthur Evans https://twitter.com/devdocdude <p>Happy New Year from the Lit team! This week we're excited to share a few updates with our fantastic community in the form of the Lit 2.1 release and some Lit Labs updates.</p> <p>Lit 2.1 consists of:</p> <ul> <li>New directives that help with looping and conditionals in your templates.</li> <li>New <code>@queryAssignedElements</code> decorator, related to the existing <code>@queryAssignedNodes</code> decorator.</li> </ul> <p>Plus we have some Lit Labs updates to make your season bright:</p> <ul> <li>The new <code>@lit-labs/observers</code> package provides reactive controllers for working with web platform observers like <code>MutationObserver</code> and <code>ResizeObserver</code>.</li> <li>Updates to the <code>@lit-labs/task</code> package.</li> <li>Updates to the <code>@lit-labs/ssr</code> package.</li> </ul> <p>For more details, read on.</p> <div class="heading h2"> <h2 id="new-directives" tabindex="-1">New directives</h2> </div> <p>Lit brings a handful of new convenience directives that make working with conditionals and looping a bit more declarative. Mostly wrappers around plain JavaScript expressions, we've found that many users appreciate the way these helpers reduce clutter in their templates.</p> <p>Like all of the directives included with Lit, these new directives are pay-as-you-go: they're shipped as separate modules, so you only bundle the directives that you choose to import.</p> <p><code>when(cond, t, f)</code> is like a ternary where the else clause is optional. It renders the first template if the condition is true, and the second if present and the condition is false.</p> <pre><code class="language-ts"><figure class="cm-editor"><div class="cm-line"><span class="tok-variableName">render</span><span class="tok-punctuation">(</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-keyword">return</span> <span class="tok-variableName">html</span>`</div><div class="cm-line"> <span class="tok-punctuation">${</span><span class="tok-variableName">when</span><span class="tok-punctuation">(</span><span class="tok-keyword">this</span><span class="tok-operator">.</span><span class="tok-propertyName">user</span><span class="tok-punctuation">,</span> <span class="tok-punctuation">(</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">=&gt;</span> <span class="tok-variableName">html</span>`User: <span class="tok-punctuation">${</span><span class="tok-keyword">this</span><span class="tok-operator">.</span><span class="tok-propertyName">user</span><span class="tok-operator">.</span><span class="tok-propertyName">username</span><span class="tok-punctuation">}</span>`<span class="tok-punctuation">,</span> <span class="tok-punctuation">(</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">=&gt;</span> <span class="tok-variableName">html</span>`Sign In...`<span class="tok-punctuation">)</span><span class="tok-punctuation">}</span></div><div class="cm-line"> `<span class="tok-punctuation">;</span></div><div class="cm-line"><span class="tok-punctuation">}</span></div></figure></code></pre> <p><code>map(iter, fn)</code> is like <code>Array.map</code>, but also works on iterators. It's similar to <code>repeat()</code> without the key function, but much smaller in code size.</p> <pre><code class="language-ts"><figure class="cm-editor"><div class="cm-line"><span class="tok-variableName">render</span><span class="tok-punctuation">(</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-keyword">return</span> <span class="tok-variableName">html</span>`</div><div class="cm-line"> <span class="tok-punctuation">&lt;</span><span class="tok-typeName">ul</span><span class="tok-punctuation">&gt;</span></div><div class="cm-line"> <span class="tok-punctuation">${</span><span class="tok-variableName">map</span><span class="tok-punctuation">(</span><span class="tok-keyword">this</span><span class="tok-operator">.</span><span class="tok-propertyName">items</span><span class="tok-punctuation">,</span> <span class="tok-punctuation">(</span><span class="tok-variableName tok-definition">i</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">=&gt;</span> <span class="tok-variableName">html</span>`<span class="tok-punctuation">&lt;</span><span class="tok-typeName">li</span><span class="tok-punctuation">&gt;</span><span class="tok-punctuation">${</span><span class="tok-variableName">i</span><span class="tok-punctuation">}</span><span class="tok-punctuation">&lt;/</span><span class="tok-typeName">li</span><span class="tok-punctuation">&gt;</span>`<span class="tok-punctuation">)</span><span class="tok-punctuation">}</span></div><div class="cm-line"> <span class="tok-punctuation">&lt;/</span><span class="tok-typeName">ul</span><span class="tok-punctuation">&gt;</span></div><div class="cm-line"> `<span class="tok-punctuation">;</span></div><div class="cm-line"><span class="tok-punctuation">}</span></div></figure></code></pre> <p><code>join(iter, t)</code> interleaves items in an iterable with a joiner value or function. Useful for adding separators between items, like <code>Array.join()</code> but instead of returning a string returns an iterable of renderable values.</p> <pre><code class="language-ts"><figure class="cm-editor"><div class="cm-line"><span class="tok-variableName">render</span><span class="tok-punctuation">(</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-keyword">return</span> <span class="tok-variableName">html</span>`</div><div class="cm-line"> <span class="tok-punctuation">${</span><span class="tok-variableName">join</span><span class="tok-punctuation">(</span><span class="tok-keyword">this</span><span class="tok-operator">.</span><span class="tok-propertyName">items</span><span class="tok-punctuation">,</span> <span class="tok-variableName">html</span>`<span class="tok-punctuation">&lt;</span><span class="tok-typeName">span</span> <span class="tok-propertyName">class</span><span class="tok-operator">=</span><span class="tok-string">"separator"</span><span class="tok-punctuation">&gt;</span>|<span class="tok-punctuation">&lt;/</span><span class="tok-typeName">span</span><span class="tok-punctuation">&gt;</span>`<span class="tok-punctuation">)</span><span class="tok-punctuation">}</span></div><div class="cm-line"> `<span class="tok-punctuation">;</span></div><div class="cm-line"><span class="tok-punctuation">}</span></div></figure></code></pre> <p><code>range(start, end, step)</code> is useful for iterating a specific number of times in a template.</p> <pre><code class="language-ts"><figure class="cm-editor"><div class="cm-line"><span class="tok-variableName">render</span><span class="tok-punctuation">(</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-keyword">return</span> <span class="tok-variableName">html</span>`</div><div class="cm-line"> <span class="tok-punctuation">${</span><span class="tok-variableName">map</span><span class="tok-punctuation">(</span><span class="tok-variableName">range</span><span class="tok-punctuation">(</span><span class="tok-number">8</span><span class="tok-punctuation">)</span><span class="tok-punctuation">,</span> <span class="tok-punctuation">(</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">=&gt;</span> <span class="tok-variableName">html</span>`<span class="tok-punctuation">&lt;</span><span class="tok-typeName">div</span> <span class="tok-propertyName">class</span><span class="tok-operator">=</span><span class="tok-string">"cell"</span><span class="tok-punctuation">&gt;</span><span class="tok-punctuation">&lt;/</span><span class="tok-typeName">div</span><span class="tok-punctuation">&gt;</span>`<span class="tok-punctuation">)</span><span class="tok-punctuation">}</span></div><div class="cm-line"> `<span class="tok-punctuation">;</span></div><div class="cm-line"><span class="tok-punctuation">}</span></div></figure></code></pre> <p><code>choose(v, cases, defaultCase)</code> chooses one template to render among a set of cases. It's like an inline switch statement.</p> <pre><code class="language-ts"><figure class="cm-editor"><div class="cm-line"><span class="tok-variableName">render</span><span class="tok-punctuation">(</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-keyword">return</span> <span class="tok-variableName">html</span>`</div><div class="cm-line"> <span class="tok-punctuation">${</span><span class="tok-variableName">choose</span><span class="tok-punctuation">(</span><span class="tok-keyword">this</span><span class="tok-operator">.</span><span class="tok-propertyName">section</span><span class="tok-punctuation">,</span> <span class="tok-punctuation">[</span></div><div class="cm-line"> <span class="tok-punctuation">[</span><span class="tok-string">'home'</span><span class="tok-punctuation">,</span> <span class="tok-punctuation">(</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">=&gt;</span> <span class="tok-variableName">html</span>`<span class="tok-punctuation">&lt;</span><span class="tok-typeName">h1</span><span class="tok-punctuation">&gt;</span>Home<span class="tok-punctuation">&lt;/</span><span class="tok-typeName">h1</span><span class="tok-punctuation">&gt;</span>`<span class="tok-punctuation">]</span><span class="tok-punctuation">,</span></div><div class="cm-line"> <span class="tok-punctuation">[</span><span class="tok-string">'about'</span><span class="tok-punctuation">,</span> <span class="tok-punctuation">(</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">=&gt;</span> <span class="tok-variableName">html</span>`<span class="tok-punctuation">&lt;</span><span class="tok-typeName">h1</span><span class="tok-punctuation">&gt;</span>About<span class="tok-punctuation">&lt;/</span><span class="tok-typeName">h1</span><span class="tok-punctuation">&gt;</span>`<span class="tok-punctuation">]</span></div><div class="cm-line"> <span class="tok-punctuation">]</span><span class="tok-punctuation">,</span></div><div class="cm-line"> <span class="tok-punctuation">(</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">=&gt;</span> <span class="tok-variableName">html</span>`<span class="tok-punctuation">&lt;</span><span class="tok-typeName">h1</span><span class="tok-punctuation">&gt;</span>Error<span class="tok-punctuation">&lt;/</span><span class="tok-typeName">h1</span><span class="tok-punctuation">&gt;</span>`<span class="tok-punctuation">)</span><span class="tok-punctuation">}</span></div><div class="cm-line"> `<span class="tok-punctuation">;</span></div><div class="cm-line"><span class="tok-punctuation">}</span></div></figure></code></pre> <div class="heading h2"> <h2 id="new-@queryassignedelements()-decorator" tabindex="-1">New @queryAssignedElements() decorator</h2> </div> <p><code>@queryAssignedElements()</code> returns the slotted or assigned elements for a given slot. It's similar to the existing <code>@queryAssignedNodes()</code> but uses the <code>slot.assignedElements()</code> method rather than <code>slot.assignedNodes()</code>. <code>@queryAssignedNodes()</code> has been updated to take an options object as an alternative to the positional argument API.</p> <pre><code class="language-ts"><figure class="cm-editor"><div class="cm-line"><span class="tok-meta">@</span><span class="tok-variableName">queryAssignedElements</span><span class="tok-punctuation">(</span><span class="tok-punctuation">{</span> <span class="tok-propertyName tok-definition">slot</span><span class="tok-punctuation">:</span> <span class="tok-string">'icon'</span> <span class="tok-punctuation">}</span><span class="tok-punctuation">)</span></div><div class="cm-line"><span class="tok-variableName">private </span><span class="tok-variableName">_icon</span><span class="tok-operator">!</span><span class="tok-punctuation">:</span> <span class="tok-variableName">Array</span>&lt;<span class="tok-typeName">HTMLElement</span>&gt;<span class="tok-punctuation">;</span></div></figure></code></pre> <div class="heading h2"> <h2 id="easy-to-use-observers-with-@lit-labsobservers" tabindex="-1">Easy to use observers with @lit-labs/observers</h2> </div> <p>In Lit Labs we've introduced a new package called <code>@lit-labs/observers</code> which contains reactive controllers that let you easily use the web platform observer APIs: MutationObserver, IntersectionObserver, ResizeObserver, and PerformanceObserver. The controllers automatically drive the host element's update lifecycle when they observe changes.</p> <pre><code class="language-ts"><figure class="cm-editor"><div class="cm-line"><span class="tok-keyword">import</span> <span class="tok-punctuation">{</span> <span class="tok-variableName tok-definition">ResizeController</span> <span class="tok-punctuation">}</span> <span class="tok-keyword">from</span> <span class="tok-string">'@lit-labs/observers/resize_controller.js'</span><span class="tok-punctuation">;</span></div><div class="cm-line"><br /></div><div class="cm-line"><span class="tok-keyword">class</span> <span class="tok-className">MyResizableElement</span> <span class="tok-keyword">extends</span> <span class="tok-variableName">LitElement</span> <span class="tok-punctuation">{</span></div><div class="cm-line"><br /></div><div class="cm-line"> <span class="tok-propertyName tok-definition">_resizeController</span> <span class="tok-operator">=</span> <span class="tok-keyword">new</span> <span class="tok-className">ResizeController</span><span class="tok-punctuation">(</span><span class="tok-keyword">this</span><span class="tok-punctuation">,</span> <span class="tok-punctuation">{</span><span class="tok-punctuation">}</span><span class="tok-punctuation">)</span><span class="tok-punctuation">;</span></div><div class="cm-line"><br /></div><div class="cm-line"> <span class="tok-propertyName tok-definition">render</span><span class="tok-punctuation">(</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-keyword">return</span> <span class="tok-variableName">html</span>`Current size is <span class="tok-punctuation">${</span><span class="tok-keyword">this</span><span class="tok-operator">.</span><span class="tok-propertyName">offsetWidth</span><span class="tok-punctuation">}</span> x <span class="tok-punctuation">${</span><span class="tok-keyword">this</span><span class="tok-operator">.</span><span class="tok-propertyName">offsetHeight</span><span class="tok-punctuation">}</span>`<span class="tok-punctuation">;</span></div><div class="cm-line"> <span class="tok-punctuation">}</span></div><div class="cm-line"><span class="tok-punctuation">}</span></div></figure></code></pre> <div class="heading h2"> <h2 id="task-updates" tabindex="-1">Task updates</h2> </div> <p>We've landed some changes to <code>@lit-labs/task</code> that allow for manually run tasks and automatic tasks with no dependencies. Tasks with no dependencies will run once when the host is connected, and all tasks can be run manually with the new <code>run()</code> method.</p> <div class="heading h2"> <h2 id="ssr-updates" tabindex="-1">SSR updates</h2> </div> <p>We've also landed some bug fixes to <code>@lit-labs/ssr</code>, reduced its NPM dependencies footprint, and refactored the <code>importModule</code> function into a new <code>ImportModule</code> class as some groundwork for upcoming changes.</p> <div class="heading h2"> <h2 id="keep-in-touch" tabindex="-1">Keep in touch</h2> </div> <p>We hope your 2022 is off to a good start. If you've tried the new releases, we'd love to hear from you. For questions and discussions, please join us on <a href="https://lit.dev/discord/">Discord</a> or on <a href="https://github.com/lit/lit/discussions">GitHub Discussions</a>. As always you can check out our documentation and code playground at <a href="https://lit.dev/">lit.dev</a> and report issues on our <a href="https://github.com/lit/lit/issues">GitHub issue tracker</a>.</p> Eleventy + Lit 2022-02-07T00:00:00Z https://lit.dev/blog/2022-02-07-eleventy/ Announcing a new Lit Labs Eleventy plugin for static rendering of Lit components Al Marks https://twitter.com/aomarks <p>The Lit team is pleased to announce an experimental preview release of <a href="https://github.com/lit/lit/tree/main/packages/labs/eleventy-plugin-lit"><code>@lit-labs/eleventy-plugin-lit</code></a>, a new plugin for <a href="https://www.11ty.dev/">Eleventy</a> that renders your Lit components as static HTML during your Eleventy build, and lets you hydrate them after your JavaScript loads.</p> <img src="https://lit.dev/images/blog/eleventy/repo-screenshot.png" width="600" height="611.52" class="block centered" /> <aside class="warning"> <p>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.</p> <p>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.</p> </aside> <p>Check it out now on <a href="https://github.com/lit/lit/tree/main/packages/labs/eleventy-plugin-lit">GitHub</a> and <a href="https://www.npmjs.com/package/@lit-labs/eleventy-plugin-lit">NPM</a>, or read on to learn more about what it does, why you might want to use it, and how it works.</p> <div class="heading h2"> <h2 id="what-does-it-do" tabindex="-1">What does it do?</h2> </div> <p>After you've added <code>@lit-labs/eleventy-plugin-lit</code> 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.</p> <p>For example, given a markdown file <code>hello.md</code>:</p> <pre><code class="language-html"><figure class="cm-editor"><div class="cm-line"># Greetings</div><div class="cm-line"><br /></div><div class="cm-line"><span class="tok-punctuation">&lt;</span><span class="tok-typeName">demo-greeter</span> <span class="tok-propertyName">name</span><span class="tok-operator">=</span><span class="tok-string">"World"</span><span class="tok-punctuation">&gt;</span><span class="tok-punctuation">&lt;/</span><span class="tok-typeName">demo-greeter</span><span class="tok-punctuation">&gt;</span></div></figure></code></pre> <p>And a component definition <code>js/demo-greeter.js</code>:</p> <pre><code class="language-js"><figure class="cm-editor"><div class="cm-line"><span class="tok-keyword">import</span> <span class="tok-punctuation">{</span><span class="tok-variableName tok-definition">LitElement</span><span class="tok-punctuation">,</span> <span class="tok-variableName tok-definition">html</span><span class="tok-punctuation">,</span> <span class="tok-variableName tok-definition">css</span><span class="tok-punctuation">}</span> <span class="tok-keyword">from</span> <span class="tok-string">'lit'</span><span class="tok-punctuation">;</span></div><div class="cm-line"><br /></div><div class="cm-line"><span class="tok-keyword">class</span> <span class="tok-className">DemoGreeter</span> <span class="tok-keyword">extends</span> <span class="tok-variableName">LitElement</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-keyword">static</span> <span class="tok-propertyName tok-definition">styles</span> <span class="tok-operator">=</span> <span class="tok-variableName">css</span>`</div><div class="cm-line"> <span class="tok-typeName">b</span> <span class="tok-punctuation">{</span> <span class="tok-propertyName">color</span><span class="tok-punctuation">:</span> <span class="tok-atom">red</span><span class="tok-punctuation">;</span> <span class="tok-punctuation">}</span></div><div class="cm-line"> `<span class="tok-punctuation">;</span></div><div class="cm-line"><br /></div><div class="cm-line"> <span class="tok-keyword">static</span> <span class="tok-propertyName tok-definition">properties</span> <span class="tok-operator">=</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-propertyName tok-definition">name</span><span class="tok-punctuation">:</span> <span class="tok-punctuation">{</span><span class="tok-punctuation">}</span><span class="tok-punctuation">,</span></div><div class="cm-line"> <span class="tok-punctuation">}</span><span class="tok-punctuation">;</span></div><div class="cm-line"><br /></div><div class="cm-line"> <span class="tok-propertyName tok-definition">render</span><span class="tok-punctuation">(</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-keyword">return</span> <span class="tok-variableName">html</span>`Hello <span class="tok-punctuation">&lt;</span><span class="tok-typeName">b</span><span class="tok-punctuation">&gt;</span><span class="tok-punctuation">${</span><span class="tok-keyword">this</span><span class="tok-operator">.</span><span class="tok-propertyName">name</span><span class="tok-punctuation">}</span><span class="tok-punctuation">&lt;/</span><span class="tok-typeName">b</span><span class="tok-punctuation">&gt;</span>!`<span class="tok-punctuation">;</span></div><div class="cm-line"> <span class="tok-punctuation">}</span></div><div class="cm-line"><span class="tok-punctuation">}</span></div><div class="cm-line"><span class="tok-variableName">customElements</span><span class="tok-operator">.</span><span class="tok-propertyName">define</span><span class="tok-punctuation">(</span><span class="tok-string">'demo-greeter'</span><span class="tok-punctuation">,</span> <span class="tok-variableName">DemoGreeter</span><span class="tok-punctuation">)</span><span class="tok-punctuation">;</span></div></figure></code></pre> <p>Then Eleventy will produce an HTML file <code>hello/index.html</code> like this:</p> <pre><code class="language-html"><figure class="cm-editor"><div class="cm-line"><span class="tok-punctuation">&lt;</span><span class="tok-typeName">h1</span><span class="tok-punctuation">&gt;</span>Greetings<span class="tok-punctuation">&lt;/</span><span class="tok-typeName">h1</span><span class="tok-punctuation">&gt;</span></div><div class="cm-line"><br /></div><div class="cm-line"><span class="tok-punctuation">&lt;</span><span class="tok-typeName">demo-greeter</span> <span class="tok-propertyName">name</span><span class="tok-operator">=</span><span class="tok-string">"World"</span><span class="tok-punctuation">&gt;</span></div><div class="cm-line"> <span class="tok-punctuation">&lt;</span><span class="tok-typeName">template</span> <span class="tok-propertyName">shadowroot</span><span class="tok-operator">=</span><span class="tok-string">"open"</span><span class="tok-punctuation">&gt;</span></div><div class="cm-line"> <span class="tok-punctuation">&lt;</span><span class="tok-typeName">style</span><span class="tok-punctuation">&gt;</span></div><div class="cm-line"> <span class="tok-typeName">b</span> <span class="tok-punctuation">{</span> <span class="tok-propertyName">color</span><span class="tok-punctuation">:</span> <span class="tok-atom">red</span><span class="tok-punctuation">;</span> <span class="tok-punctuation">}</span></div><div class="cm-line"> <span class="tok-punctuation">&lt;/</span><span class="tok-typeName">style</span><span class="tok-punctuation">&gt;</span></div><div class="cm-line"> Hello <span class="tok-punctuation">&lt;</span><span class="tok-typeName">b</span><span class="tok-punctuation">&gt;</span>World<span class="tok-punctuation">&lt;/</span><span class="tok-typeName">b</span><span class="tok-punctuation">&gt;</span>!</div><div class="cm-line"> <span class="tok-punctuation">&lt;/</span><span class="tok-typeName">template</span><span class="tok-punctuation">&gt;</span></div><div class="cm-line"><span class="tok-punctuation">&lt;/</span><span class="tok-typeName">demo-greeter</span><span class="tok-punctuation">&gt;</span></div></figure></code></pre> <p>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!</p> <p>Later, when the JavaScript definition of <code>&lt;demo-greeter&gt;</code> has finally loaded, the statically rendered component is upgraded to its fully interactive JavaScript implementation through a process called <em>hydration</em>.</p> <div class="heading h2"> <h2 id="why-should-i-use-it" tabindex="-1">Why should I use it?</h2> </div> <p>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.</p> <p>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.</p> <p>For a deeper dive into the benefits of static rendering, check out <em><a href="https://developers.google.com/web/updates/2019/02/rendering-on-the-web">Rendering on the Web</a></em>, and for a discussion of how to measure this aspect of web performance, check out <em><a href="https://web.dev/lcp/">Largest Contentful Paint (LCP)</a></em>.</p> <div class="heading h2"> <h2 id="how-does-it-work" tabindex="-1">How does it work?</h2> </div> <div class="heading h3"> <h3 id="lit-labs-ssr" tabindex="-1">Lit Labs SSR</h3> </div> <p>The plugin uses <code>@lit-labs/ssr</code> 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 <code>render</code> function. This special <code>render</code> function behaves much like the <code>render</code> 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.</p> <p>For more information about <code>@lit-labs/ssr</code>, check out its <a href="https://github.com/lit/lit/tree/main/packages/labs/ssr">GitHub repo</a>. We'll be expanding the documentation soon to help developers integrate <code>@lit-labs/ssr</code> into more tools and frameworks!</p> <div class="heading h3"> <h3 id="declarative-shadow-dom" tabindex="-1">Declarative Shadow DOM</h3> </div> <p>When <code>@lit-labs/ssr</code> renders a component, it uses <code>&lt;template shadowroot&gt;</code> HTML elements to represent the component's shadow DOM and styles. When the browser HTML parser encounters a <code>&lt;template shadowroot&gt;</code>, 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.</p> <p>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 <a href="https://github.com/lit/lit/tree/main/packages/labs/eleventy-plugin-lit#polyfill">documented</a> in the <code>@lit-labs/eleventy-plugin-lit</code> README.</p> <p>For more information about Declarative Shadow DOM, check out <em><a href="https://web.dev/declarative-shadow-dom/">Declarative Shadow DOM</a></em>.</p> <div class="heading h3"> <h3 id="hydration" tabindex="-1">Hydration</h3> </div> <p>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.</p> <p><em>Hydration</em> is the process where a statically rendered component is upgraded to its JavaScript implementation, becoming responsive and interactive.</p> <p>Lit comes with automatic support for hydration via the special <code>@lit-labs/ssr-client/lit-element-hydrate-support.js</code> 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.</p> <p>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.</p> <div class="heading h2"> <h2 id="what's-next" tabindex="-1">What's next?</h2> </div> <p>Check out the <a href="https://github.com/lit/lit/tree/main/packages/labs/eleventy-plugin-lit#roadmap">roadmap</a> for <code>@lit-labs/eleventy-plugin-lit</code> for some of the main features and fixes you can expect to land over the coming months.</p> <p>If you try out <code>@lit-labs/eleventy-plugin-lit</code>, let us know if you have any suggestions or find any problems by starting a <a href="https://github.com/lit/lit/discussions">discussion</a> or filing an <a href="https://github.com/lit/lit/issues">issue</a>.</p> Lit on Discord! 2022-09-06T00:00:00Z https://lit.dev/blog/2022-09-06-discord/ We've launched a brand new Lit Discord server, and here's why you should join it now! Al Marks https://twitter.com/aomarks <p>We've just launched a brand new <a href="https://lit.dev/discord/">Lit Discord server</a>, and we'd love for you to <a href="https://lit.dev/discord/">join it now</a>! Everybody is welcome, whether you are brand new to Lit, or an experienced user.</p> <p>We think the Lit Discord will be the best place to chat with the Lit community, talk to the Lit dev team, get help using Lit, and show off your Lit projects! We also plan to host special events there, using both chat and voice!</p> <img src="https://lit.dev/images/blog/discord/discord-screenshot.png" width="600" height="385.25" class="block centered" /> <div class="heading h2"> <h2 id="why-discord" tabindex="-1">Why Discord?</h2> </div> <p>Here's what we like best about Discord:</p> <ol> <li> <p><strong>It's easy to be in <em>many</em> communities</strong>, becuase you can quickly switch between them.</p> <p>There are already Discords for Modern Web, Shoelace, Vaadin, Material, Astro, and many other open source projects, so we think it will be great to be able to easily jump between them, share announcements, and more.</p> </li> <li> <p><strong>Syntax highlighting</strong>, including for nested html tagged template literals!</p> </li> <li> <p><strong>Traction &amp; growth</strong>. Discord has had huge growth in recent years, and new open source projects seem to be choosing Discord more often than not now. We think that's becuase using Discord is a great experience, and because the friction to joining new Discord servers is low after you've started using it.</p> </li> </ol> <div class="heading h2"> <h2 id="what's-happening-to-slack" tabindex="-1">What's happening to Slack?</h2> </div> <p>The <em>Lit &amp; Friends</em> workspace on Slack will be going into read-only mode on <strong>Tuesday, September 13, 2022</strong>. After that, you'll be able to read existing messages, but won't be able to post new ones. We've already sent a message to every channel about these plans.</p> <p>We decided to retire the Slack instead of maintaining both because we want to encourage more communication and less silos. Slack has served the Lit community well, but we think now is the right time to move to Discord!</p> Get the lowdown on Lit Labs 2022-10-18T00:00:00Z https://lit.dev/blog/2022-10-18-lit-labs-event/ Join us for a virtual event on October 24th 2022 at 10AM PDT to learn all about Lit Labs! Elliott Marquez https://twitter.com/techytacos <p>The Lit team is hosting a virtual event on <strong>Monday, October 24th 2022 at 10AM PDT</strong> to talk about all of the exciting work going on in Lit Labs. We'll give an overview of the Lit Labs program, followed by detailed presentations on several Labs packages. And we'll let you know how you can help get these packages across the finish line and shape the future of Lit!</p> <p>To make sure you don't miss it, <a href="https://www.youtube.com/watch?v=l6Gn5uV83sw"><strong>go to the live stream</strong></a> and sign up for notifications.</p> <img src="https://lit.dev/images/blog/labs-event/lit-labs.svg" width="720" class="block centered" /> <div class="heading h2"> <h2 id="what-is-lit-labs" tabindex="-1">What is Lit Labs?</h2> </div> <p><a href="https://lit.dev/docs/libraries/labs/">Lit Labs</a> is an umbrella for Lit packages under development that we are actively seeking community engagement on. These projects may be experimental or incomplete, or simply looking for real-world feedback. Lit Labs projects are published under the <a href="https://www.npmjs.com/search?q=%40lit-labs"><code>@lit-labs</code> npm scope</a>.</p> <div class="heading h2"> <h2 id="what-will-be-covered-at-the-lit-labs-event" tabindex="-1">What will be covered at the Lit Labs event?</h2> </div> <p>We'll show you how individual Labs packages can help you in your Web Component projects, and let you know what each package needs to graduate from Labs. Here are the packages we'll be covering:</p> <ul> <li><a href="https://github.com/lit/lit/tree/main/packages/labs/task">Task</a></li> <li><a href="https://github.com/lit/lit/tree/main/packages/labs/virtualizer">Virtualizer</a></li> <li><a href="https://github.com/lit/lit/tree/main/packages/labs/motion">Motion</a></li> <li><a href="https://github.com/lit/lit/tree/main/packages/labs/context">Context</a></li> <li><a href="https://github.com/lit/lit/tree/main/packages/labs/react">React</a></li> <li><a href="https://github.com/lit/lit/tree/main/packages/labs/cli">CLI</a>-generated Framework Wrappers</li> <li><a href="https://github.com/lit/lit/tree/main/packages/labs/ssr">SSR</a></li> <li><a href="https://github.com/lit/lit/tree/main/packages/labs/observers">Observers</a></li> </ul> <div class="heading h2"> <h2 id="when-is-it-again" tabindex="-1">When is it, again?</h2> </div> <p>The event will be on <strong>Monday, October 24th 2022 at 10AM PDT</strong>. Make sure to sign up for YouTube reminders and notifications <a href="https://www.youtube.com/watch?v=l6Gn5uV83sw"><strong>on the event page</strong></a> so you don't miss it!</p> Announcing Lit 3.0 Pre-releases 2023-05-15T00:00:00Z https://lit.dev/blog/2023-05-15-lit-3.0-prerelease/ Get an early look at the upcoming Lit 3.0 release. Justin Fagnani https://twitter.com/justinfagnani <h1>Announcing Lit 3.0 Pre-releases</h1> <p>The Lit team is excited to announce the first pre-releases of Lit 3.0!</p> <p>Lit 3.0 is our first major version since <a href="https://lit.dev/blog/2021-04-21-lit-2.0-meet-lit-all-over-again/">introducing the unified Lit project and Lit 2.0</a> two years ago. We really value stability and backwards compatibility for our community, so we've focused on adding new features with minor versions of the core libraries and new labs packages, and not making any breaking changes.</p> <p>But the time is right for just a few breaking changes that will improve development velocity and testing stability on the core Lit project.</p> <div class="heading h2"> <h2 id="changes" tabindex="-1">Changes</h2> </div> <p>Lit 3.0 adds no new features, because new features are generally not breaking changes and can be added in minor versions, according to semver. The Lit 3.0 release is an opportunity to make a few breaking changes that trim out some technical debt to unlock new features we have scheduled for our 3.x release series.</p> <p>The Lit 3.0 changes are mostly in browser support, removing deprecated APIs, and how packages are published. If you run Lit 2.x with no deprecation warnings, this should be a seamless upgrade!</p> <p>Here are the biggest things Lit 3.0 changes:</p> <ul> <li>IE11 is no longer supported.</li> <li>Lit's npm modules are now published as ES2021.</li> <li>APIs deprecated during the Lit 1.x release timeframe have been removed.</li> <li>SSR hydration support modules were moved to the <code>@lit-labs/ssr-client</code> package.</li> </ul> <p>A preview of the <a href="https://lit.dev/docs/v3/releases/upgrade/">Lit v2 to v3 upgrade guide</a> is available on the site.</p> <p>Detailed change logs can be found <a href="https://github.com/lit/lit/releases?q=%22-pre.0%22&amp;expanded=true">on GitHub</a>.</p> <div class="heading h2"> <h2 id="trying-the-pre-releases" tabindex="-1">Trying the Pre-releases</h2> </div> <p>We would love your help testing the new versions, to ensure a smooth upgrade process with the final releases. We're especially interested in making sure the new language version works with your toolchains. We expect some users may need to upgrade their tooling to the latest versions.</p> <p>You can try the pre-releases out by updating your package.json file to include the following:</p> <pre><code class="language-json"><figure class="cm-editor"><div class="cm-line"> <span class="tok-string">"lit"</span><span class="tok-punctuation">:</span> <span class="tok-string">"^3.0.0-pre.0"</span></div><div class="cm-line"> <span class="tok-string">"lit-html"</span><span class="tok-punctuation">:</span> <span class="tok-string">"^3.0.0-pre.0"</span></div><div class="cm-line"> <span class="tok-string">"lit-element"</span><span class="tok-punctuation">:</span> <span class="tok-string">"^4.0.0-pre.0"</span></div><div class="cm-line"> <span class="tok-string">"@lit/reactive-element"</span><span class="tok-punctuation">:</span> <span class="tok-string">"^2.0.0-pre.0"</span></div></figure></code></pre> <p>You can also use the <code>pre</code> npm tag, like <code>npm i lit@pre</code>.</p> <p>All other packages, like labs packages, have pre-release versions too that depend on the pre-release core libraries. If you depend on those you'll have to update them too. If you're more daring you can use npm overrides to select the pre-releases even for dependencies. This should work for most dependencies.</p> <p>Even if dependencies are using Lit 2.x, the good news is that Lit 2.x and Lit 3.x are interoperable, because:</p> <ol> <li>The inherent interoperability web components: components built with different libraries work together, including those build with different versions of Lit.</li> <li>We made interop of core features like templates and directives a priority for Lit 2. You can share templates, directives, decorators, etc., across Lit versions.</li> </ol> <div class="heading h2"> <h2 id="docs" tabindex="-1">Docs</h2> </div> <p>We are preparing new docs for 3.0 on <a href="https://lit.dev/">lit.dev</a>. Even though these will be mostly the same as 2.x, we are clarifying the browser and toolchain support, and want to make it easy to select the right docs set for the version you're using to enable future changes specific to to 3.x. At the 3.0 launch, we’ll archive the 2.x docs (but they will remain available in the doc version dropdown, as will 1.x). During the 3.0 pre-release phase, 2.x will remain the default, and you can select v3 from the dropdown next to the Documentation tab.</p> <div class="heading h2"> <h2 id="feedback" tabindex="-1">Feedback</h2> </div> <p>We hope you enjoy Lit 3.0! If you have questions or feedback, please let us know in <a href="https://github.com/lit/lit/issues">GitHub issues</a> or on our <a href="https://lit.dev/discord/">Lit and Friends Discord</a>.</p> <p><strong>Thanks!,</strong></p> <p><strong>-The Lit Team</strong></p> Lit 3.0 Prerelease 2 and more! 2023-09-28T00:00:00Z https://lit.dev/blog/2023-09-27-lit-3.0-prerelease-2/ Today we are publishing the second prerelease of Lit 3.0. Lit Team https://twitter.com/buildWithLit <h1>Lit 3.0 Prerelease 2 and more!</h1> <p>Today we are publishing the second prerelease of Lit 3.0.</p> <p>This prerelease includes:</p> <ul> <li>The core Lit 3.0 packages</li> <li>The first graduating class of Lit Labs: Task, Context, and React</li> <li>Our first preview of our new optimizing template compiler</li> <li>A Preact Signals integration library</li> </ul> <p>There are many other packages in this prerelease. See the full list and how to try them out <a href="https://lit.dev/blog/2023-09-27-lit-3.0-prerelease-2/#try">here</a>.</p> <div class="heading h2"> <h2 id="lit-3.0-prerelease-2" tabindex="-1">Lit 3.0 Prerelease 2</h2> </div> <p>As we <a href="https://lit.dev/blog/2023-05-15-lit-3.0-prerelease/">announced with the first prerelease</a>, Lit 3.0 is a breaking change that most notably removes support for IE11. As a new major version, Lit 3.0 is intended to have no new features, since new features can be added in non-breaking minor versions.</p> <div class="heading h3"> <h3 id="breaking-changes" tabindex="-1">Breaking changes</h3> </div> <ul> <li>IE11 is no longer supported.</li> <li>Lit's npm modules are now published as ES2021.</li> <li>APIs deprecated with the Lit 2.0 release have been removed.</li> <li>SSR hydration support modules are moved to the <code>@lit-labs/ssr-client</code> package.</li> <li>Decorator behavior has been unified between TypeScript experimental decorators and standard decorators.</li> <li>Support was removed for Babel decorators version &quot;2018-09&quot;</li> </ul> <p>These breaking changes should have minimal impact for most users – based on testing against Google's codebase, they impact about one in a thousand elements – and allow our project to move forward more efficiently.</p> <div class="heading h3"> <h3 id="new:-standard-decorators-support" tabindex="-1">New: standard decorators support</h3> </div> <p>The one new feature that we <em>did</em> add to Lit 3.0 is support for the TC39 standard decorators specification to our <em>existing</em> decorators.</p> <p>The new decorator spec has reached Stage 3 in TC39, meaning that browsers and compilers are now implementing them. This is a huge step for Lit! The arrival of standard decorators allows us to begin the process of moving to a decorator implementation that won't require a compiler to use.</p> <p>It's very important to us to make the upgrade path from experimental decorators as smooth as possible. To accomplish this we made our existing decorators support the standard spec and made them work with the new <code>accessor</code> keyword in experimental decorator mode.</p> <p>This way you can use Lit decorators with auto-accessors (using the <code>accessor</code> keyword) so that the same call site works with both settings:</p> <pre><code class="language-ts"><figure class="cm-editor"><div class="cm-line"><span class="tok-keyword">class</span> <span class="tok-className">MyElement</span> <span class="tok-keyword">extends</span> <span class="tok-variableName">LitElement</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-meta">@</span><span class="tok-variableName">property</span><span class="tok-punctuation">(</span><span class="tok-punctuation">)</span></div><div class="cm-line"> accessor <span class="tok-propertyName tok-definition">myProperty</span> <span class="tok-operator">=</span> <span class="tok-string">'hello'</span><span class="tok-punctuation">;</span></div><div class="cm-line"><span class="tok-punctuation">}</span></div></figure></code></pre> <p>Once all decorator call sites in your project use the <code>accessor</code> keyword, you can build with <code>experimentalDecorators</code> set to <code>true</code> or <code>false</code> without a change in behavior.</p> <p>But in order to make these hybrid decorators have consistent behavior in both modes we had to make a few minor breaking changes to our experimental decorators:</p> <ul> <li>We now call <code>requestUpdate()</code> automatically for <code>@property</code> and <code>@state</code> decorated accessors where previously that was the setter's responsibility.</li> <li>The value of an accessor is read on first render and used as the initial value for <code>changedProperties</code> and attribute reflection.</li> <li><code>@property</code> and <code>@state</code> must be used on the setter for hand-written accessors.</li> </ul> <p>Standard decorator mode requires <a href="https://devblogs.microsoft.com/typescript/announcing-typescript-5-2/#decorator-metadata">TypeScript 5.2</a> or <a href="https://babeljs.io/blog/2023/09/25/7.23.0">Babel 7.23</a> with the <a href="https://babeljs.io/docs/babel-plugin-proposal-decorators"><code>@babel/plugin-proposal-decorators</code></a> plugin using decorator version <code>&quot;2023-05&quot;</code>.</p> <div class="heading h4"> <h4 id="outstanding-issues-with-standard-decorators" tabindex="-1">Outstanding issues with standard decorators</h4> </div> <ol> <li>We still need to update our decorator documentation on lit.dev</li> <li>The TypeScript and Babel emit for standard decorators is quite a bit larger than for TypeScript experimental decorators. We still recommend <code>experimentalDecorators: true</code> for production.</li> </ol> <div class="heading h2"> <h2 id="new-lit-template-compiler!" tabindex="-1">New Lit template compiler!</h2> </div> <p>The releases today also include the first preview of our new template compiler: <a href="https://www.npmjs.com/package/@lit-labs/compiler"><code>@lit-labs/compiler</code></a>.</p> <p>Our compiler is a TypeScript transform that rewrites lit-html templates into a prepared representation so that the template prep steps are skipped at runtime. This can improve first render performance, sometimes dramatically. All template behavior remains exactly the same.</p> <p>We plan on offering the compiler in a number of tool plugin formats, but for now we just have a TypeScript transform. One of the easiest ways to use it is via Rollup's TypeScript plugin, which allows you to add transforms:</p> <p><code>rollup.config.js</code>:</p> <pre><code class="language-js"><figure class="cm-editor"><div class="cm-line"><span class="tok-keyword">import</span> <span class="tok-variableName tok-definition">typescript</span> <span class="tok-keyword">from</span> <span class="tok-string">'@rollup/plugin-typescript'</span><span class="tok-punctuation">;</span></div><div class="cm-line"><span class="tok-keyword">import</span> <span class="tok-punctuation">{</span><span class="tok-variableName tok-definition">compileLitTemplates</span><span class="tok-punctuation">}</span> <span class="tok-keyword">from</span> <span class="tok-string">'@lit-labs/compiler'</span><span class="tok-punctuation">;</span></div><div class="cm-line"><br /></div><div class="cm-line"><span class="tok-keyword">export</span> <span class="tok-keyword">default</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-comment">// ...</span></div><div class="cm-line"> <span class="tok-propertyName tok-definition">plugins</span><span class="tok-punctuation">:</span> <span class="tok-punctuation">[</span></div><div class="cm-line"> <span class="tok-variableName">typescript</span><span class="tok-punctuation">(</span><span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-propertyName tok-definition">transformers</span><span class="tok-punctuation">:</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-propertyName tok-definition">before</span><span class="tok-punctuation">:</span> <span class="tok-punctuation">[</span><span class="tok-variableName">compileLitTemplates</span><span class="tok-punctuation">(</span><span class="tok-punctuation">)</span><span class="tok-punctuation">]</span><span class="tok-punctuation">,</span></div><div class="cm-line"> <span class="tok-punctuation">}</span><span class="tok-punctuation">,</span></div><div class="cm-line"> <span class="tok-punctuation">}</span><span class="tok-punctuation">)</span><span class="tok-punctuation">,</span></div><div class="cm-line"> <span class="tok-comment">// other rollup plugins</span></div><div class="cm-line"> <span class="tok-punctuation">]</span><span class="tok-punctuation">,</span></div><div class="cm-line"><span class="tok-punctuation">}</span><span class="tok-punctuation">;</span></div></figure></code></pre> <div class="heading h2"> <h2 id="preact-signals-integration" tabindex="-1">Preact Signals integration</h2> </div> <p>Signals: they're so hot right now!</p> <p>Many frameworks are adopting signals – observable holders of state and computation – for performance and DX improvements. Lit already has a very efficient rendering system, and in preliminary tests signals aren't a clear performance improvement.</p> <p>For Lit developers we think signals promise to offer a convenient and relatively simple option for shared observable state, a recurring need in our community. So we are starting to explore what it would look like to integrate signals with Lit with a new <a href="https://www.npmjs.com/package/@lit-labs/preact-signals"><code>@lit-labs/preact-signals</code></a> package.</p> <p>This package provides three ways to use <a href="https://preactjs.com/guide/v10/signals/">Preact Signals</a>:</p> <ol> <li>A <code>SignalWatcher</code> mixin, which makes a component automatically watch all signals used during updates.</li> <li>A <code>watch()</code> directive, which watches one signal and updates a binding with it.</li> <li>A special <code>html</code> template tag that auto-applies the <code>watch()</code> directive to all bindings that use signals.</li> </ol> <p>Here's an example of using the <code>SignalWatcher</code> mixin:</p> <pre><code class="language-ts"><figure class="cm-editor"><div class="cm-line"><span class="tok-keyword">import</span> <span class="tok-punctuation">{</span><span class="tok-variableName tok-definition">LitElement</span><span class="tok-punctuation">,</span> <span class="tok-variableName tok-definition">html</span><span class="tok-punctuation">}</span> <span class="tok-keyword">from</span> <span class="tok-string">'lit'</span><span class="tok-punctuation">;</span></div><div class="cm-line"><span class="tok-keyword">import</span> <span class="tok-punctuation">{</span><span class="tok-variableName tok-definition">customElement</span><span class="tok-punctuation">,</span> <span class="tok-variableName tok-definition">property</span><span class="tok-punctuation">}</span> <span class="tok-keyword">from</span> <span class="tok-string">'lit'</span><span class="tok-punctuation">;</span></div><div class="cm-line"><span class="tok-keyword">import</span> <span class="tok-punctuation">{</span><span class="tok-variableName tok-definition">SignalWatcher</span><span class="tok-punctuation">,</span> <span class="tok-variableName tok-definition">signal</span><span class="tok-punctuation">}</span> <span class="tok-keyword">from</span> <span class="tok-string">'@lit-labs/preact-signals'</span><span class="tok-punctuation">;</span></div><div class="cm-line"><br /></div><div class="cm-line"><span class="tok-keyword">const</span> <span class="tok-variableName tok-definition">count</span> <span class="tok-operator">=</span> <span class="tok-variableName">signal</span><span class="tok-punctuation">(</span><span class="tok-number">0</span><span class="tok-punctuation">)</span><span class="tok-punctuation">;</span></div><div class="cm-line"><br /></div><div class="cm-line"><span class="tok-meta">@</span><span class="tok-variableName">customElement</span><span class="tok-punctuation">(</span><span class="tok-string">'signal-example'</span><span class="tok-punctuation">)</span></div><div class="cm-line"><span class="tok-keyword">export</span> <span class="tok-keyword">class</span> <span class="tok-className">SignalExample</span> <span class="tok-keyword">extends</span> <span class="tok-variableName">SignalWatcher</span><span class="tok-punctuation">(</span><span class="tok-variableName">LitElement</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">{</span></div><div class="cm-line"><br /></div><div class="cm-line"> <span class="tok-propertyName tok-definition">render</span><span class="tok-punctuation">(</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-keyword">return</span> <span class="tok-variableName">html</span>`</div><div class="cm-line"> <span class="tok-punctuation">&lt;</span><span class="tok-typeName">p</span><span class="tok-punctuation">&gt;</span>The count is <span class="tok-punctuation">${</span><span class="tok-variableName">count</span><span class="tok-operator">.</span><span class="tok-propertyName">value</span><span class="tok-punctuation">}</span><span class="tok-punctuation">&lt;/</span><span class="tok-typeName">p</span><span class="tok-punctuation">&gt;</span></div><div class="cm-line"> <span class="tok-punctuation">&lt;</span><span class="tok-typeName">button</span> <span class="tok-propertyName">@click</span><span class="tok-operator">=</span><span class="tok-punctuation">${</span><span class="tok-keyword">this</span><span class="tok-operator">.</span><span class="tok-propertyName">_onClick</span><span class="tok-punctuation">}</span><span class="tok-punctuation">&gt;</span>Increment<span class="tok-punctuation">&lt;</span><span class="tok-typeName">button</span><span class="tok-punctuation">&gt;</span><span class="tok-punctuation">&lt;/</span><span class="tok-typeName">button</span><span class="tok-punctuation">&gt;</span><span class="tok-punctuation">&lt;/</span><span class="tok-typeName">button</span><span class="tok-punctuation">&gt;</span></div><div class="cm-line"> `<span class="tok-punctuation">;</span></div><div class="cm-line"> <span class="tok-punctuation">}</span></div><div class="cm-line"><br /></div><div class="cm-line"> <span class="tok-keyword">private</span> <span class="tok-propertyName tok-definition">_onClick</span><span class="tok-punctuation">(</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-comment">// A change to the signal value causes the element to re-render!</span></div><div class="cm-line"> <span class="tok-variableName">count</span><span class="tok-operator">.</span><span class="tok-propertyName">value</span> <span class="tok-operator">=</span> <span class="tok-variableName">count</span><span class="tok-operator">.</span><span class="tok-propertyName">value</span> <span class="tok-operator">+</span> <span class="tok-number">1</span><span class="tok-punctuation">;</span></div><div class="cm-line"> <span class="tok-punctuation">}</span></div><div class="cm-line"><span class="tok-punctuation">}</span></div></figure></code></pre> <div class="heading h3"> <h3 id="why-preact-signals" tabindex="-1">Why Preact Signals?</h3> </div> <p>One issue that signals present for web components is that there are many different signals implementations and no interoperability between them. This goes against the interoperability goals of web components, so for now, rather than build our own signals package or pick just one that we endorse, we plan on offering integration packages to be able to use various signal libraries with Lit.</p> <p>These integrations will be relatively simple because we have two straight-forward ways of using signals:</p> <ol> <li>Treat a component's update lifecycle as an effect, so that it's run when any signals it accesses (like in templates) changes. This integrates signals with Lit's batching async lifecycle for good performance when many signals change.</li> <li>Use a directive to wire a signal directly to a location in DOM.</li> </ol> <p>We chose Preact's signals library for our first integration because it's a relatively small, fast, and easy-to-understand implementation published to npm as standard JS modules.</p> <div class="heading h2"> <h2 id="lit-labs-graduations" tabindex="-1">Lit Labs graduations</h2> </div> <p>We are also graduating our first set of Lit Labs packages: Context, Task, and React.</p> <p>These packages have a new home in the <code>@lit</code> npm scope, but are otherwise exactly the same as the current labs versions. The labs packages have been updated to depend on and re-export the non-labs versions so that they share a single implementation.</p> <div class="heading h2"> <h2 id="try" tabindex="-1">Trying out the prerelease</h2> </div> <p>To try out the prerelease, update your <code>package.json</code> to depend on the prerelease package versions.</p> <p>The packages in the prerelease are:</p> <ul> <li><code>lit@3.0.0-pre.1</code></li> <li><code>lit-element@4.0.0-pre.1</code></li> <li><code>lit-html@3.0.0-pre.1</code></li> <li><code>@lit/reactive-element@2.0.0-pre.1</code></li> <li><code>@lit/context@1.0.0-pre.0</code></li> <li><code>@lit/react@1.0.0-pre.0</code></li> <li><code>@lit/task@1.0.0-pre.0</code></li> <li><code>@lit-labs/compiler@1.0.0-pre.0</code></li> <li><code>@lit-labs/preact-signals@1.0.0-pre.0</code></li> </ul> <p>You should also update dependencies on our other packages so that they pick up the Lit prerelease as well.</p> <details> <summary>Other Lit prerelease packages</summary> <ul> <li><code>@lit/localize-tools@0.7.0-pre.1</code></li> <li><code>@lit/localize@0.12.0-pre.1</code></li> <li><code>@lit/ts-transformers@2.0.0-pre.1</code></li> <li><code>@lit-labs/analyzer@0.10.0-pre.0</code></li> <li><code>@lit-labs/cli-localize@0.2.0-pre.1</code></li> <li><code>@lit-labs/cli@0.6.1-pre.0</code></li> <li><code>@lit-labs/context@0.5.0-pre.0</code></li> <li><code>@lit-labs/eleventy-plugin-lit@1.0.2-pre.1</code></li> <li><code>@lit-labs/gen-manifest@0.3.0-pre.0</code></li> <li><code>@lit-labs/gen-utils@0.3.0-pre.0</code></li> <li><code>@lit-labs/gen-wrapper-react@0.3.0-pre.0</code></li> <li><code>@lit-labs/gen-wrapper-vue@0.3.0-pre.0</code></li> <li><code>@lit-labs/motion@1.0.5-pre.0</code></li> <li><code>@lit-labs/nextjs@0.1.2-pre.1</code></li> <li><code>@lit-labs/observers@2.0.1-pre.1</code></li> <li><code>@lit-labs/react@2.1.1-pre.0</code></li> <li><code>@lit-labs/router@0.1.2-pre.1</code></li> <li><code>@lit-labs/scoped-registry-mixin@1.0.2-pre.1</code></li> <li><code>@lit-labs/ssr-client@1.1.4-pre.1</code></li> <li><code>@lit-labs/ssr-dom-shim@1.1.2-pre.1</code></li> <li><code>@lit-labs/ssr-react@0.2.1-pre.0</code></li> <li><code>@lit-labs/ssr@3.1.8-pre.0</code></li> <li><code>@lit-labs/task@3.1.0-pre.0</code></li> <li><code>@lit-labs/testing@0.2.2-pre.1</code></li> <li><code>@lit-labs/virtualizer@2.0.8-pre.0</code></li> <li><code>@lit-labs/vue-utils@0.1.1-pre.1</code></li> </ul> </details> <p>Remember that Lit 2.x and Lit 3.0 are interoperable, so even if some of your dependencies are using Lit 2.x you can try the Lit 3.0 prerelease on your components!</p> <div class="heading h3"> <h3 id="docs" tabindex="-1">Docs</h3> </div> <p>You can view the Lit 3.0 docs on lit.dev at <a href="https://lit.dev/docs/v3/">https://lit.dev/docs/v3/</a> .</p> <p>We are still updating some of the docs, our main task until the final release of Lit 3.0.</p> <div class="heading h2"> <h2 id="feedback" tabindex="-1">Feedback</h2> </div> <p>We hope you enjoy Lit 3.0! If you have questions or feedback, please let us know in <a href="https://github.com/lit/lit/issues">GitHub issues</a> or on our <a href="https://lit.dev/discord/">Lit and Friends Discord</a>.</p> <hr /> <p><strong>Thanks! - The Lit Team</strong></p> Lit Launch Day: Lit 3.0, Labs graduations, a compiler and more! 2023-10-10T00:00:00Z https://lit.dev/blog/2023-10-10-lit-3.0/ We're launching the next major version of Lit Lit Team https://twitter.com/buildWithLit <h1>Lit Launch Day: Lit 3.0, Labs graduations, a compiler and more!</h1> <p>It's launch day for the Lit project, and we have a bunch of exciting releases to share with the Lit and web components communities!</p> <p>After several months of development, the Lit team is happy to announce the final release of Lit 3.0 – our first major version since Lit 2.0 in early 2021, the first graduating class of Lit Labs packages <code>@lit/react</code>, <code>@lit/task</code>, and <code>@lit/context</code>, and two bonus releases <code>@lit-labs/compiler</code> and <code>@lit-labs/preact-signals</code>.</p> <p>This is a big release, so here are links to the individual announcements:</p> <ul> <li><a href="https://lit.dev/blog/2023-10-10-lit-3.0/#lit-3.0">Lit 3.0</a></li> <li><a href="https://lit.dev/blog/2023-10-10-lit-3.0/#compiler">The New Lit Template Compiler</a></li> <li><a href="https://lit.dev/blog/2023-10-10-lit-3.0/#preact-signals-integration">Preact Signals Integration</a></li> <li><a href="https://lit.dev/blog/2023-10-10-lit-3.0/#labs-graduation">Labs Graduation Day</a></li> </ul> <div class="heading h2"> <h2 id="lit-3.0" tabindex="-1">Lit 3.0: Bye, Bye IE, Hello TC39 Decorators!</h2> </div> <p>We value stability for our community. Breaking changes are a cost that every user and the entire ecosystem has to bear: projects have to upgrade, multiple versions can be included in an app, and documents, samples, tutorials, starter kits, etc. have to be updated for every breaking change.</p> <p>So we want to only make breaking changes when we must, or when the benefits to the community clearly outweigh the costs. For benefits we tend look for decreased code size, increased performance, reduction in maintenance burden, and better alignment with standards.</p> <p>We also follow <a href="https://semver.org/">semantic versioning</a>, so we increase the major version only when there are breaking changes. New features typically arrive in new <em>minor</em> versions, which are backwards compatible. So Lit 3.0 is intended to only be a breaking change, with no new features. There is one exception though – standard decorators!</p> <div class="heading h3"> <h3 id="breaking-changes" tabindex="-1">Breaking changes</h3> </div> <p>For Lit 3.0, the biggest breaking change is that we've dropped IE11 support. After surveying our developer community, we feel like now is the right time to say goodbye to IE, and very few customers will be affected.</p> <p>This release is also an opportunity to make a few additional breaking changes that trim out some technical debt to unlock new features we have scheduled for our 3.x release series and beyond.</p> <p>These changes are hopefully minor for most customers. If you run Lit 2.x with no deprecation warnings, and use toolchain that supports modern JS, this should be a seamless upgrade!</p> <p>Here are the biggest things Lit 3.0 changes:</p> <ul> <li>IE11 is no longer supported.</li> <li>Lit's npm modules are now published as ES2021.</li> <li>APIs deprecated with the Lit 2.0 release have been removed.</li> <li>SSR hydration support modules were moved to the <code>@lit-labs/ssr-client</code> package.</li> <li>Decorator behavior has been unified between TypeScript experimental decorators and standard decorators.</li> <li>Support was removed for Babel decorators version &quot;2018-09&quot;</li> </ul> <p>Full details in the <a href="https://lit.dev/docs/v3/releases/upgrade/">the upgrade guide</a>.</p> <div class="heading h3"> <h3 id="new:-standard-decorators-support" tabindex="-1">New: standard decorators support</h3> </div> <p>The one new feature that we <em>did</em> add to Lit 3.0 is support for the TC39 standard decorators specification to our <em>existing</em> decorators.</p> <p>The new decorator spec has reached Stage 3 in TC39, meaning that browsers and compilers are now implementing them. This is a huge step for Lit! The arrival of standard decorators allows us to begin the process of moving to a decorator implementation that won't require a compiler to use.</p> <p>It's very important to us to make the upgrade path from experimental decorators as smooth as possible. To accomplish this we made our existing decorators support the standard spec and made them work with the new <code>accessor</code> keyword in experimental decorator mode.</p> <p>This way you can use Lit decorators with auto-accessors (using the <code>accessor</code> keyword) so that the same call site works with both settings:</p> <pre><code class="language-ts"><figure class="cm-editor"><div class="cm-line"><span class="tok-keyword">class</span> <span class="tok-className">MyElement</span> <span class="tok-keyword">extends</span> <span class="tok-variableName">LitElement</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-meta">@</span><span class="tok-variableName">property</span><span class="tok-punctuation">(</span><span class="tok-punctuation">)</span></div><div class="cm-line"> accessor <span class="tok-propertyName tok-definition">myProperty</span> <span class="tok-operator">=</span> <span class="tok-string">'hello'</span><span class="tok-punctuation">;</span></div><div class="cm-line"><span class="tok-punctuation">}</span></div></figure></code></pre> <p>Once all decorator call sites in your project use the <code>accessor</code> keyword, you can build with <code>experimentalDecorators</code> set to <code>true</code> or <code>false</code> without a change in behavior.</p> <p>But in order to make these hybrid decorators have consistent behavior in both modes, we had to make a few minor breaking changes to our experimental decorators:</p> <ul> <li>We now call <code>requestUpdate()</code> automatically for <code>@property</code> and <code>@state</code> decorated accessors where previously that was the setter's responsibility.</li> <li>The value of an accessor is read on first render and used as the initial value for <code>changedProperties</code> and attribute reflection.</li> <li><code>@property</code> and <code>@state</code> must be used on the setter for hand-written accessors.</li> </ul> <p>Standard decorator mode requires <a href="https://devblogs.microsoft.com/typescript/announcing-typescript-5-2/#decorator-metadata">TypeScript 5.2</a> or <a href="https://babeljs.io/blog/2023/09/25/7.23.0">Babel 7.23</a> with the <a href="https://babeljs.io/docs/babel-plugin-proposal-decorators"><code>@babel/plugin-proposal-decorators</code></a> plugin using decorator version <code>&quot;2023-05&quot;</code>.</p> <div class="heading h3"> <h3 id="upgrading" tabindex="-1">Upgrading</h3> </div> <p>The upgrade from Lit 2.0 should be seamless for the vast majority of users. You can usually upgrade your npm dependency version with:</p> <pre><code class="language-sh"><figure class="cm-editor"><div class="cm-line"><span class="cm-nonmatchingBracket">&gt;</span> npm i lit@latest</div></figure></code></pre> <p>You can find more details and how to handle the changes in the <a href="https://lit.dev/docs/v3/releases/upgrade/">Lit 3 upgrade guide</a>.</p> <p>Detailed change logs can be found <a href="https://github.com/lit/lit/releases?q=lit%403.0.0&amp;expanded=true">on GitHub</a>.</p> <div class="heading h2"> <h2 id="compiler" tabindex="-1">Even Faster Rendering with the new Lit Template Compiler</h2> </div> <p>The new <a href="https://www.npmjs.com/package/@lit-labs/compiler"><code>@lit-labs/compiler</code></a> Labs package provides a <a href="https://github.com/itsdouges/typescript-transformer-handbook#the-basics">TypeScript Transformer</a> that can be run over your JavaScript or TypeScript files to do build-time preparation of Lit templates that Lit would normally do at runtime.</p> <p><img src="https://lit.dev/images/blog/3.0-launch/compiler-benchmarks.png" alt="Lit Compiler benchmarks" /></p> <p>While not all templates will see rendering performance improvements from compilation, on our &quot;template heavy&quot; benchmark we measured a 46% faster first render, and a 21% faster update!</p> <p>To try out <code>@lit-labs/compiler</code> today, you’ll need a build step that accepts a TypeScript transformer. For Rollup.js users, this could be <code>@rollup/plugin-typescript</code>. An example <code>rollup.config.js</code> file might look like:</p> <pre><code class="language-js"><figure class="cm-editor"><div class="cm-line"><span class="tok-comment">// File: rollup.config.js</span></div><div class="cm-line"><span class="tok-keyword">import</span> <span class="tok-variableName tok-definition">typescript</span> <span class="tok-keyword">from</span> <span class="tok-string">'@rollup/plugin-typescript'</span><span class="tok-punctuation">;</span></div><div class="cm-line"><span class="tok-keyword">import</span> <span class="tok-punctuation">{</span><span class="tok-variableName tok-definition">compileLitTemplates</span><span class="tok-punctuation">}</span> <span class="tok-keyword">from</span> <span class="tok-string">'@lit-labs/compiler'</span><span class="tok-punctuation">;</span></div><div class="cm-line"><br /></div><div class="cm-line"><span class="tok-keyword">export</span> <span class="tok-keyword">default</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-comment">// ...</span></div><div class="cm-line"> <span class="tok-propertyName tok-definition">plugins</span><span class="tok-punctuation">:</span> <span class="tok-punctuation">[</span></div><div class="cm-line"> <span class="tok-variableName">typescript</span><span class="tok-punctuation">(</span><span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-propertyName tok-definition">transformers</span><span class="tok-punctuation">:</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-propertyName tok-definition">before</span><span class="tok-punctuation">:</span> <span class="tok-punctuation">[</span><span class="tok-variableName">compileLitTemplates</span><span class="tok-punctuation">(</span><span class="tok-punctuation">)</span><span class="tok-punctuation">]</span><span class="tok-punctuation">,</span></div><div class="cm-line"> <span class="tok-punctuation">}</span><span class="tok-punctuation">,</span></div><div class="cm-line"> <span class="tok-punctuation">}</span><span class="tok-punctuation">)</span><span class="tok-punctuation">,</span></div><div class="cm-line"> <span class="tok-comment">// other rollup plugins</span></div><div class="cm-line"> <span class="tok-punctuation">]</span><span class="tok-punctuation">,</span></div><div class="cm-line"><span class="tok-punctuation">}</span><span class="tok-punctuation">;</span></div></figure></code></pre> <div class="heading h3"> <h3 id="what-does-the-transform-do" tabindex="-1">What does the transform do?</h3> </div> <p>Given some source code containing an <code>html</code> tag function to declare templates:</p> <pre><code class="language-ts"><figure class="cm-editor"><div class="cm-line"><span class="tok-keyword">const</span> <span class="tok-variableName tok-definition">hi</span> <span class="tok-operator">=</span> <span class="tok-punctuation">(</span><span class="tok-variableName tok-definition">name</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">=&gt;</span> <span class="tok-variableName">html</span>`<span class="tok-punctuation">&lt;</span><span class="tok-typeName">h1</span><span class="tok-punctuation">&gt;</span>Hello <span class="tok-punctuation">${</span><span class="tok-variableName">name</span><span class="tok-punctuation">}</span>!<span class="tok-punctuation">&lt;/</span><span class="tok-typeName">h1</span><span class="tok-punctuation">&gt;</span>`<span class="tok-punctuation">;</span></div></figure></code></pre> <p>The Lit template transform will remove the html tag function and replace it with something similar to the following:</p> <pre><code class="language-ts"><figure class="cm-editor"><div class="cm-line"><span class="tok-keyword">const</span> <span class="tok-variableName tok-definition">b</span> <span class="tok-operator">=</span> <span class="tok-punctuation">(</span><span class="tok-variableName tok-definition">s</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">=&gt;</span> <span class="tok-variableName">s</span><span class="tok-punctuation">;</span></div><div class="cm-line"><span class="tok-keyword">const</span> <span class="tok-variableName tok-definition">lit_template_1</span> <span class="tok-operator">=</span> <span class="tok-punctuation">{</span><span class="tok-propertyName tok-definition">h</span><span class="tok-punctuation">:</span> <span class="tok-variableName">b</span><span class="tok-string2">`&lt;h1&gt;Hello &lt;?&gt;&lt;/h1&gt;`</span><span class="tok-punctuation">,</span> <span class="tok-propertyName tok-definition">parts</span><span class="tok-punctuation">:</span> <span class="tok-punctuation">[</span><span class="tok-punctuation">{</span><span class="tok-propertyName tok-definition">type</span><span class="tok-punctuation">:</span> <span class="tok-number">2</span><span class="tok-punctuation">,</span> <span class="tok-propertyName tok-definition">index</span><span class="tok-punctuation">:</span> <span class="tok-number">1</span><span class="tok-punctuation">}</span><span class="tok-punctuation">]</span><span class="tok-punctuation">}</span><span class="tok-punctuation">;</span></div><div class="cm-line"><span class="tok-keyword">const</span> <span class="tok-variableName tok-definition">hi</span> <span class="tok-operator">=</span> <span class="tok-punctuation">(</span><span class="tok-variableName tok-definition">name</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">=&gt;</span> <span class="tok-punctuation">(</span><span class="tok-punctuation">{</span><span class="tok-propertyName tok-definition">_$litType$</span><span class="tok-punctuation">:</span> <span class="tok-variableName">lit_template_1</span><span class="tok-punctuation">,</span> <span class="tok-propertyName tok-definition">values</span><span class="tok-punctuation">:</span> <span class="tok-punctuation">[</span><span class="tok-variableName">name</span><span class="tok-punctuation">]</span><span class="tok-punctuation">}</span><span class="tok-punctuation">)</span><span class="tok-punctuation">;</span></div></figure></code></pre> <p>We call this a compiled template, and it behaves the same as your authored template, except that when Lit renders the compiled template, Lit can skip an internal render phase called the Prepare phase, meaning you get a quicker initial render.</p> <p>As you can see in the above example, there is some additional code generated as part of the transform. We’ve measured that minified and compressed, you may get a 5% increase in file size for the compiled file. This is something we have plans to address.</p> <div class="heading h3"> <h3 id="looking-forward" tabindex="-1">Looking forward</h3> </div> <p>We’d love to hear from you and get feedback on your experience using the transform, as well as hear what you’d like to see optimized! Leave that feedback in this <a href="https://github.com/lit/lit/discussions/4117">Labs Feedback discussion</a>. We’d also like to learn more about what build systems Lit is used in, and welcome contributions!</p> <p>This is just the beginning. With this new package we have a foundation for layering on additional build-time optimizations. Some optimizations we’ve thought about:</p> <ul> <li>For a Lit app which can be completely compiled, we could vend an import of lit-html that is smaller.</li> <li>Add an option to the compiler transform to also minify the HTML in the templates.</li> <li>Do build-time evaluation of other parts of the Lit API, such as compiling away the built-in Lit decorators.</li> <li>Compress the emitted output file by applying domain-specific file compression.</li> </ul> <div class="heading h2"> <h2 id="preact-signals-integration" tabindex="-1">Preact Signals integration</h2> </div> <p>Signals: they're so hot right now!</p> <p>Many frameworks are adopting signals – reactive holders of state and computation – for performance and DX improvements. Lit already has a very efficient rendering system, and our preliminary benchmarks don't show a clear performance wins from signals.</p> <p>For Lit developers we think signals promise to offer a convenient and relatively simple option for shared observable state, a recurring need in our community. So we are starting to explore what it would look like to integrate signals with Lit with a new <a href="https://www.npmjs.com/package/@lit-labs/preact-signals"><code>@lit-labs/preact-signals</code></a> package.</p> <p>This package provides three ways to use <a href="https://preactjs.com/guide/v10/signals/">Preact Signals</a>:</p> <ol> <li>A <code>SignalWatcher</code> mixin, which makes a component automatically watch all signals used during updates.</li> <li>A <code>watch()</code> directive, which watches one signal and updates a binding with it.</li> <li>A special <code>html</code> template tag that auto-applies the <code>watch()</code> directive to all bindings that use signals.</li> </ol> <p>Here's an example of using the <code>SignalWatcher</code> mixin:</p> <pre><code class="language-ts"><figure class="cm-editor"><div class="cm-line"><span class="tok-keyword">import</span> <span class="tok-punctuation">{</span><span class="tok-variableName tok-definition">LitElement</span><span class="tok-punctuation">,</span> <span class="tok-variableName tok-definition">html</span><span class="tok-punctuation">}</span> <span class="tok-keyword">from</span> <span class="tok-string">'lit'</span><span class="tok-punctuation">;</span></div><div class="cm-line"><span class="tok-keyword">import</span> <span class="tok-punctuation">{</span><span class="tok-variableName tok-definition">customElement</span><span class="tok-punctuation">,</span> <span class="tok-variableName tok-definition">property</span><span class="tok-punctuation">}</span> <span class="tok-keyword">from</span> <span class="tok-string">'lit'</span><span class="tok-punctuation">;</span></div><div class="cm-line"><span class="tok-keyword">import</span> <span class="tok-punctuation">{</span><span class="tok-variableName tok-definition">SignalWatcher</span><span class="tok-punctuation">,</span> <span class="tok-variableName tok-definition">signal</span><span class="tok-punctuation">}</span> <span class="tok-keyword">from</span> <span class="tok-string">'@lit-labs/preact-signals'</span><span class="tok-punctuation">;</span></div><div class="cm-line"><br /></div><div class="cm-line"><span class="tok-keyword">const</span> <span class="tok-variableName tok-definition">count</span> <span class="tok-operator">=</span> <span class="tok-variableName">signal</span><span class="tok-punctuation">(</span><span class="tok-number">0</span><span class="tok-punctuation">)</span><span class="tok-punctuation">;</span></div><div class="cm-line"><br /></div><div class="cm-line"><span class="tok-meta">@</span><span class="tok-variableName">customElement</span><span class="tok-punctuation">(</span><span class="tok-string">'signal-example'</span><span class="tok-punctuation">)</span></div><div class="cm-line"><span class="tok-keyword">export</span> <span class="tok-keyword">class</span> <span class="tok-className">SignalExample</span> <span class="tok-keyword">extends</span> <span class="tok-variableName">SignalWatcher</span><span class="tok-punctuation">(</span><span class="tok-variableName">LitElement</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">{</span></div><div class="cm-line"><br /></div><div class="cm-line"> <span class="tok-propertyName tok-definition">render</span><span class="tok-punctuation">(</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-keyword">return</span> <span class="tok-variableName">html</span>`</div><div class="cm-line"> <span class="tok-punctuation">&lt;</span><span class="tok-typeName">p</span><span class="tok-punctuation">&gt;</span>The count is <span class="tok-punctuation">${</span><span class="tok-variableName">count</span><span class="tok-operator">.</span><span class="tok-propertyName">value</span><span class="tok-punctuation">}</span><span class="tok-punctuation">&lt;/</span><span class="tok-typeName">p</span><span class="tok-punctuation">&gt;</span></div><div class="cm-line"> <span class="tok-punctuation">&lt;</span><span class="tok-typeName">button</span> <span class="tok-propertyName">@click</span><span class="tok-operator">=</span><span class="tok-punctuation">${</span><span class="tok-keyword">this</span><span class="tok-operator">.</span><span class="tok-propertyName">_onClick</span><span class="tok-punctuation">}</span><span class="tok-punctuation">&gt;</span>Increment<span class="tok-punctuation">&lt;/</span><span class="tok-typeName">button</span><span class="tok-punctuation">&gt;</span></div><div class="cm-line"> `<span class="tok-punctuation">;</span></div><div class="cm-line"> <span class="tok-punctuation">}</span></div><div class="cm-line"><br /></div><div class="cm-line"> <span class="tok-keyword">private</span> <span class="tok-propertyName tok-definition">_onClick</span><span class="tok-punctuation">(</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-comment">// A change to the signal value causes the element to re-render!</span></div><div class="cm-line"> <span class="tok-variableName">count</span><span class="tok-operator">.</span><span class="tok-propertyName">value</span> <span class="tok-operator">=</span> <span class="tok-variableName">count</span><span class="tok-operator">.</span><span class="tok-propertyName">value</span> <span class="tok-operator">+</span> <span class="tok-number">1</span><span class="tok-punctuation">;</span></div><div class="cm-line"> <span class="tok-punctuation">}</span></div><div class="cm-line"><span class="tok-punctuation">}</span></div></figure></code></pre> <div class="heading h3"> <h3 id="why-preact-signals" tabindex="-1">Why Preact Signals?</h3> </div> <p>One issue that signals present for web components is that there are many different signals implementations and no interoperability between them. This goes against the interoperability goals of web components, so for now, rather than build our own signals package or pick just one that we endorse, we plan on offering integration packages to be able to use various signal libraries with Lit.</p> <p>These integrations will be relatively simple because we have two straight-forward ways of using signals:</p> <ol> <li>Treat a component's update lifecycle as an effect, so that it's run when any signals it accesses (like in templates) changes. This integrates signals with Lit's batching async lifecycle for good performance when many signals change.</li> <li>Use a directive to wire a signal directly to a location in DOM.</li> </ol> <p>We chose Preact's signals library for our first integration because it's a relatively small, fast, and easy-to-understand implementation published to npm as standard JS modules.</p> <div class="heading h2"> <h2 id="labs-graduation" tabindex="-1">Lit Labs Graduation Day</h2> </div> <p>We are also graduating our first set of Lit Labs packages: Context, Task, and React.</p> <p>These packages have a new home in the <code>@lit</code> npm scope, but are otherwise exactly the same as the current labs versions. The labs packages have been updated to depend on and re-export the non-labs versions so that they share a single implementation.</p> <p>Find them in their new npm homes: <a href="https://www.npmjs.com/package/@lit/react"><code>@lit/react</code></a>, <a href="https://www.npmjs.com/package/@lit/task"><code>@lit/task</code></a>, and <a href="https://www.npmjs.com/package/@lit/context"><code>@lit/context</code></a></p> <p>These packages can now be considered stable, and have documentation and examples on lit.dev!</p> <p>Current users of these packages under the <code>@lit-labs</code> scope can migrate by first updating to the latest version of those packages to test for any breakages, then update the import to use the <code>@lit</code> scoped package. The latest <code>@lit-labs</code> scoped packages will receive the same updates until the next major version of the <code>@lit</code> scoped package.</p> <p>Thank you so much to everyone in the community who has tested out a Labs package, filed issues, discussed features, and led these packages to graduation! 🎓</p> <div class="heading h3"> <h3 id="react" tabindex="-1">React</h3> </div> <p>While custom elements can be used in React projects as is, there are some rough edges around their usage, namely:</p> <ul> <li>Setting properties on elements (rather than attributes)</li> <li>Adding handlers for custom events</li> <li>Type checking custom elements and their props</li> </ul> <p>Some of these are being addressed by React in a future version, but they are currently only present in experimental builds not recommended for production.</p> <p><code>@lit/react</code> allows creation of React components wrapping the custom element. The created components can be idiomatic to React such that users of the component do not have to worry about the inner web component implementation.</p> <p>It is useful for both web component authors who wish to vend React versions of their components for users to reach a wider audience, as well as React developers who wish to use a neat web component that they found in their project more ergonomically.</p> <p><code>@lit-labs/react</code> has been our most popular labs project by far with over 500k weekly npm downloads and is already being used by many web component libraries to provide React versions of their components to users.</p> <p>Read more about it at our <a href="https://lit.dev/docs/frameworks/react">React framework integration</a> documentation.</p> <div class="heading h3"> <h3 id="task" tabindex="-1">Task</h3> </div> <p>Working with asynchronous data in a Lit component tends to involve boiler plate code, and there are a few subtle edge cases to handle. Task is a simple ReactiveController that automatically handles these edge cases and makes it easy to do asynchronous work correctly.</p> <p>Some considerations include:</p> <ul> <li>Conditionally rendering different content while the data is pending, retrieved, or the request failed</li> <li>Handling race conditions, ensuring the data for the latest request is kept and previous requests are cancelled or ignored if completed later</li> </ul> <p>We've found <code>@lit-labs/task</code> indispensable when working with asynchronous values. It includes a number of refinements since its initial release, like how every task receives an <code>AbortSignal</code> that the library ensures aborts if the task run becomes obsolete.</p> <p>We are happy for it to officially graduate and encourage everyone to use it! For more info see the new <a href="https://lit.dev/docs/data/task/">Async Tasks</a> docs page.</p> <div class="heading h3"> <h3 id="context" tabindex="-1">Context</h3> </div> <p><code>@lit/context</code> is an interoperable system for an element to request data from any of its ancestors. It's useful for shared elements to receive configuration from their environment, for elements in a composable plugin system to exhange data, and as an interoperable DOM-based dependency injection system.</p> <p>Start by creating a context using the <code>createContext()</code> function. A context acts as a key, for the consumer and provider of the data to identify each other.</p> <p>Then, on the providing element, declare a property with the <code>@provide</code> decorator. As with the main <code>lit</code> decorators, these work as standard decorators, and with TypeScript's <code>experimentalDecorators</code> option enabled. The property's value will be made available to any descendents of the element that consume the context.</p> <p>Finally, on the consuming element, declare a property with the <code>@consume</code> decorator. When the element attaches to the DOM it will receive the current value of the first ancestor that provides the context. If called with <code>subscribe: true</code> then it will also receive updates as the value changes.</p> <p>For more info, see the <a href="https://lit.dev/docs/data/context/">Context</a> documentation.</p> <div class="heading h2"> <h2 id="we're-excited-to-see-what-you-build-with-lit!" tabindex="-1">We're excited to see what you build with Lit!</h2> </div> <p>We're constantly amazed by the things the Lit and web components communities are building, and can't wait to see what's going to be made with Lit 3.0 and our growing collection of helper libraries.</p> <p>Please drop by our <a href="https://lit.dev/discord/">Discord server</a>, <a href="https://github.com/lit/lit/discussions">GitHub discussions</a> or find us on the <a href="https://twitter.com/buildWithLit">site formerly known as Twitter</a> to join our community and show us what you're up to!</p> <p><strong>Thanks!,</strong></p> <p><strong>-The Lit Team</strong></p> Bringing Signals to Lit Labs 2024-10-08T00:00:00Z https://lit.dev/blog/2024-10-08-signals/ The new Signals package integrates the TC39 Signals proposal with Lit Lit Team https://twitter.com/buildWithLit <h1>Announcing @lit-labs/signals: Integrating the TC39 Signals Proposal with Lit</h1> <p>We’re thrilled to announce the release of our newest Lit Labs package, <a href="https://www.npmjs.com/package/@lit-labs/signals"><code>@lit-labs/signals</code></a>, which integrates the <a href="https://github.com/proposal-signals/signal-polyfill">polyfill</a> for the exciting new <a href="https://github.com/tc39/proposal-signals">TC39 Signals Proposal</a> directly with Lit. This package provides a powerful, reactive way to manage state in your web applications by allowing you to use shared, observable signals that automatically update components when their values change.</p> <p>Signals are quickly becoming a core feature in the JavaScript ecosystem, and the TC39 proposal has the potential to unify signals and how we manage state and reactivity across various libraries and frameworks.</p> <p>Though the proposal is in its early stages, you can start experimenting with signals and <code>@lit-labs/signals</code> today to see how building components and apps on a universal reactivity primitive might work for you.</p> <div class="heading h2"> <h2 id="what-are-signals" tabindex="-1">What Are Signals?</h2> </div> <p>In simple terms, <strong>signals</strong> are observable data structures that hold values or computations. When the value of a signal changes, all components or parts of your app that depend on it are automatically notified and updated. This is particularly useful in UIs where multiple components might need to share and react to changes in state.</p> <div class="heading h3"> <h3 id="key-benefits-of-standards-based-signals" tabindex="-1">Key Benefits of Standards-Based Signals</h3> </div> <ol> <li><strong>Shared observable state</strong>: Signals are great for managing state shared across multiple components. If one component updates a signal, all others using it will automatically update as well.</li> <li><strong>Pinpoint updates</strong>: Signals enable precisely targeted re-renders, potentially improving performance by processing only bindings whose signal- backed values have changed, skipping other bindings in the same templates.</li> <li><strong>Interoperability</strong>: The standardization of signals means different libraries and frameworks can use signals interoperably, reducing the need for complex adapters and improving compatibility.</li> </ol> <div class="heading h2"> <h2 id="why-we're-excited-about-@lit-labssignals" tabindex="-1">Why We're Excited About <code>@lit-labs/signals</code></h2> </div> <p>Lit is already known for its lightweight, performant, and declarative approach to building web components. But Lit is tightly focused on helping you build reusable, encapsulated <em>components</em>. Lit is not a framework and does not precribe how to model your <em>data</em> or make it observable.</p> <p>Lit's reactivity is by default relatively <em>shallow</em>. Components automatically update when their own reactive properties change, but not when nested properties change. Responding to deep property changes has either required manual update requests, or the integration of a state management system like Redux or MobX.</p> <p>Signals give us many of the same deep observability abilities as these state management systems, but with a smaller, simpler API, and the potential to be a common standard across a large ecosystem of utilies, components, and frameworks.</p> <p>Signals aren't entirely new to Lit. We previously released the <code>@lit-labs/preact-signals</code> package, but we were somewhat unsatisfied with the need to build a Lit integration for a specific signals library, and potentially every signals library that Lit developers might want to use.</p> <p>Standardized signals in JavaScript would let us build just one integration (and eventually add signals support directly in Lit's core), and enable interop between signal-using libraries in the same spirit of the interop that web components enable.</p> <p>The new <code>@lit-labs/signals</code> package makes it super easy to use the new signals proposal from within your Lit components.</p> <p>Let’s dive into a few examples...</p> <div class="heading h3"> <h3 id="example-1:-a-shared-counter" tabindex="-1">Example 1: A Shared Counter</h3> </div> <p>Here’s a simple example of a shared counter using <code>@lit-labs/signals</code>. To enable signal-based reactivity in this component, we just use the <code>SignalWatcher</code> mixin in our Custom Element definition; any signals we read from will automatically be observed, triggering updates whenever their values change:</p> <pre><code class="language-ts"><figure class="cm-editor"><div class="cm-line"><span class="tok-keyword">import</span> <span class="tok-punctuation">{</span><span class="tok-variableName tok-definition">LitElement</span><span class="tok-punctuation">,</span> <span class="tok-variableName tok-definition">html</span><span class="tok-punctuation">}</span> <span class="tok-keyword">from</span> <span class="tok-string">'lit'</span><span class="tok-punctuation">;</span></div><div class="cm-line"><span class="tok-keyword">import</span> <span class="tok-punctuation">{</span><span class="tok-variableName tok-definition">customElement</span><span class="tok-punctuation">}</span> <span class="tok-keyword">from</span> <span class="tok-string">'lit/decorators.js'</span><span class="tok-punctuation">;</span></div><div class="cm-line"><span class="tok-keyword">import</span> <span class="tok-punctuation">{</span><span class="tok-variableName tok-definition">SignalWatcher</span><span class="tok-punctuation">,</span> <span class="tok-variableName tok-definition">signal</span><span class="tok-punctuation">}</span> <span class="tok-keyword">from</span> <span class="tok-string">'@lit-labs/signals'</span><span class="tok-punctuation">;</span></div><div class="cm-line"><br /></div><div class="cm-line"><span class="tok-comment">// This is a standard TC39 signal that uses the signals polyfill.</span></div><div class="cm-line"><span class="tok-comment">// The signal is shared across all component instances.</span></div><div class="cm-line"><span class="tok-keyword">const</span> <span class="tok-variableName tok-definition">count</span> <span class="tok-operator">=</span> <span class="tok-variableName">signal</span><span class="tok-punctuation">(</span><span class="tok-number">0</span><span class="tok-punctuation">)</span><span class="tok-punctuation">;</span></div><div class="cm-line"><br /></div><div class="cm-line"><span class="tok-meta">@</span><span class="tok-variableName">customElement</span><span class="tok-punctuation">(</span><span class="tok-string">'shared-counter'</span><span class="tok-punctuation">)</span></div><div class="cm-line"><span class="tok-keyword">export</span> <span class="tok-keyword">class</span> <span class="tok-className">SharedCounterComponent</span> <span class="tok-keyword">extends</span> <span class="tok-variableName">SignalWatcher</span><span class="tok-punctuation">(</span><span class="tok-variableName">LitElement</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-propertyName tok-definition">render</span><span class="tok-punctuation">(</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-comment">// Just by using the signal in your template, your component will update</span></div><div class="cm-line"> <span class="tok-comment">// when the signal changes.</span></div><div class="cm-line"> <span class="tok-keyword">return</span> <span class="tok-variableName">html</span>`</div><div class="cm-line"> <span class="tok-punctuation">&lt;</span><span class="tok-typeName">p</span><span class="tok-punctuation">&gt;</span>The count is <span class="tok-punctuation">${</span><span class="tok-variableName">count</span><span class="tok-operator">.</span><span class="tok-propertyName">get</span><span class="tok-punctuation">(</span><span class="tok-punctuation">)</span><span class="tok-punctuation">}</span><span class="tok-punctuation">&lt;/</span><span class="tok-typeName">p</span><span class="tok-punctuation">&gt;</span></div><div class="cm-line"> <span class="tok-punctuation">&lt;</span><span class="tok-typeName">button</span> <span class="tok-propertyName">@click</span><span class="tok-operator">=</span><span class="tok-punctuation">${</span><span class="tok-keyword">this</span><span class="tok-operator">.</span><span class="tok-propertyName">increment</span><span class="tok-punctuation">}</span><span class="tok-punctuation">&gt;</span>Increment<span class="tok-punctuation">&lt;/</span><span class="tok-typeName">button</span><span class="tok-punctuation">&gt;</span></div><div class="cm-line"> `<span class="tok-punctuation">;</span></div><div class="cm-line"> <span class="tok-punctuation">}</span></div><div class="cm-line"><br /></div><div class="cm-line"> <span class="tok-propertyName tok-definition">increment</span><span class="tok-punctuation">(</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-variableName">count</span><span class="tok-operator">.</span><span class="tok-propertyName">set</span><span class="tok-punctuation">(</span><span class="tok-variableName">count</span><span class="tok-operator">.</span><span class="tok-propertyName">get</span><span class="tok-punctuation">(</span><span class="tok-punctuation">)</span> <span class="tok-operator">+</span> <span class="tok-number">1</span><span class="tok-punctuation">)</span><span class="tok-punctuation">;</span></div><div class="cm-line"> <span class="tok-punctuation">}</span></div><div class="cm-line"><span class="tok-punctuation">}</span></div></figure></code></pre> <p>With this approach, any number of <code>&lt;shared-counter&gt;</code> components can be added to the DOM, and all will reflect the same counter value, automatically updating when the signal changes.</p> <p>You can also <a href="https://lit.dev/playground/#sample=examples/signals">see this example in the Lit Playground</a>.</p> <div class="heading h3"> <h3 id="example-2:-pinpoint-dom-updates" tabindex="-1">Example 2: Pinpoint DOM Updates</h3> </div> <p>Using the <code>watch</code> directive, we can also achieve <strong>pinpoint updates</strong> targeting individual bindings rather than an entire component:</p> <pre><code class="language-ts"><figure class="cm-editor"><div class="cm-line"><span class="tok-keyword">import</span> <span class="tok-punctuation">{</span><span class="tok-variableName tok-definition">LitElement</span><span class="tok-punctuation">,</span> <span class="tok-variableName tok-definition">html</span><span class="tok-punctuation">}</span> <span class="tok-keyword">from</span> <span class="tok-string">'lit'</span><span class="tok-punctuation">;</span></div><div class="cm-line"><span class="tok-keyword">import</span> <span class="tok-punctuation">{</span><span class="tok-variableName tok-definition">customElement</span><span class="tok-punctuation">}</span> <span class="tok-keyword">from</span> <span class="tok-string">'lit/decorators.js'</span><span class="tok-punctuation">;</span></div><div class="cm-line"><span class="tok-keyword">import</span> <span class="tok-punctuation">{</span><span class="tok-variableName tok-definition">SignalWatcher</span><span class="tok-punctuation">,</span> <span class="tok-variableName tok-definition">watch</span><span class="tok-punctuation">,</span> <span class="tok-variableName tok-definition">signal</span><span class="tok-punctuation">}</span> <span class="tok-keyword">from</span> <span class="tok-string">'@lit-labs/signals'</span><span class="tok-punctuation">;</span></div><div class="cm-line"><br /></div><div class="cm-line"><span class="tok-keyword">const</span> <span class="tok-variableName tok-definition">count</span> <span class="tok-operator">=</span> <span class="tok-variableName">signal</span><span class="tok-punctuation">(</span><span class="tok-number">0</span><span class="tok-punctuation">)</span><span class="tok-punctuation">;</span></div><div class="cm-line"><br /></div><div class="cm-line"><span class="tok-meta">@</span><span class="tok-variableName">customElement</span><span class="tok-punctuation">(</span><span class="tok-string">'pinpoint-counter'</span><span class="tok-punctuation">)</span></div><div class="cm-line"><span class="tok-keyword">export</span> <span class="tok-keyword">class</span> <span class="tok-className">PinpointCounter</span> <span class="tok-keyword">extends</span> <span class="tok-variableName">SignalWatcher</span><span class="tok-punctuation">(</span><span class="tok-variableName">LitElement</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-propertyName tok-definition">render</span><span class="tok-punctuation">(</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-keyword">return</span> <span class="tok-variableName">html</span>`</div><div class="cm-line"> <span class="tok-punctuation">&lt;</span><span class="tok-typeName">p</span><span class="tok-punctuation">&gt;</span>The count is <span class="tok-punctuation">${</span><span class="tok-variableName">watch</span><span class="tok-punctuation">(</span><span class="tok-variableName">count</span><span class="tok-punctuation">)</span><span class="tok-punctuation">}</span><span class="tok-punctuation">&lt;/</span><span class="tok-typeName">p</span><span class="tok-punctuation">&gt;</span></div><div class="cm-line"> <span class="tok-punctuation">&lt;</span><span class="tok-typeName">button</span> <span class="tok-propertyName">@click</span><span class="tok-operator">=</span><span class="tok-punctuation">${</span><span class="tok-keyword">this</span><span class="tok-operator">.</span><span class="tok-propertyName">increment</span><span class="tok-punctuation">}</span><span class="tok-punctuation">&gt;</span>Increment<span class="tok-punctuation">&lt;/</span><span class="tok-typeName">button</span><span class="tok-punctuation">&gt;</span></div><div class="cm-line"> `<span class="tok-punctuation">;</span></div><div class="cm-line"> <span class="tok-punctuation">}</span></div><div class="cm-line"><br /></div><div class="cm-line"> <span class="tok-propertyName tok-definition">increment</span><span class="tok-punctuation">(</span><span class="tok-punctuation">)</span> <span class="tok-punctuation">{</span></div><div class="cm-line"> <span class="tok-variableName">count</span><span class="tok-operator">.</span><span class="tok-propertyName">set</span><span class="tok-punctuation">(</span><span class="tok-variableName">count</span><span class="tok-operator">.</span><span class="tok-propertyName">get</span><span class="tok-punctuation">(</span><span class="tok-punctuation">)</span> <span class="tok-operator">+</span> <span class="tok-number">1</span><span class="tok-punctuation">)</span><span class="tok-punctuation">;</span></div><div class="cm-line"> <span class="tok-punctuation">}</span></div><div class="cm-line"><span class="tok-punctuation">}</span></div></figure></code></pre> <p>Here, only the binding displaying the count is processed when the signal changes, skipping unnecessary work and improving performance.</p> <div class="heading h2"> <h2 id="future-work" tabindex="-1">Future Work</h2> </div> <p>This is just the beginning of our exploration of signals integration for Lit. Coming soon, we will add more utilities to <code>@lit-labs/signals</code> for incrementally rendering changes from collections, easily running side-effects in components, and using signals for reactive properties.</p> <p>Eventually—as the proposed standard progresses and we gain experience using signals in Lit—signals will likely become part of the core library.</p> <p>The Lit team is working closely with the TC39 Signals Proposal champions to ensure that signals work great for Lit, web components, and plain-DOM use cases. We can't overstate how much potential we see in signals to form an interoperable reactivity primitive that works across libraries and components without requiring a centralized framework.</p> <div class="heading h2"> <h2 id="try-it-out-and-give-feedback" tabindex="-1">Try It Out and Give Feedback</h2> </div> <p>We’re eager to get feedback from the community as you experiment with this new package. As part of the <strong>Lit Labs</strong> family, <code>@lit-labs/signals</code> is still experimental and may undergo significant changes based on user feedback and advancements in the TC39 Signals Proposal.</p> <p>To get started, simply install the package:</p> <pre><code class="language-sh"><figure class="cm-editor"><div class="cm-line">npm i @lit-labs/signals</div></figure></code></pre> <p>We’d love to hear your thoughts, so please try it out, and let us know how it works for you.</p> <ul> <li>Preliminary docs are available at <a href="https://lit.dev/docs/data/signals/">lit.dev/docs/data/signals/</a></li> <li>You can share feedback on the GitHub <a href="https://github.com/lit/lit/discussions/4779">feedback discussion</a></li> <li>Report issues in the <a href="https://github.com/lit/lit/issues">Lit monorepo issues</a></li> <li>Join us on our <a href="https://lit.dev/discord/">Discord server</a> to chat!</li> </ul> <p>We’re excited to see what you’ll build with signals and how they will shape the future of state management in web applications!</p> <p><strong>Thanks!</strong></p> <p><strong>-The Lit Team</strong></p> Lit is Joining the OpenJS Foundation! 2025-10-14T00:00:00Z https://lit.dev/blog/2025-10-14-openjs/ Lit is officially joining the OpenJS Foundation as an Impact Project! Lit Team https://twitter.com/buildWithLit <div class="heading h2"> <h2 id="announcing-lit's-admission-to-the-openjs-foundation-as-an-impact-project" tabindex="-1">Announcing Lit's admission to the OpenJS Foundation as an Impact Project</h2> </div> <p>This morning at JSConf, the OpenJS Foundation announced that <a href="https://openjsf.org/blog/lit-moves-to-openjs-foundation">Lit is officially joining as an Impact Project</a>! We are incredibly excited to share this news with you. After a long journey working through the necessary administrative and legal processes, Lit is moving from a solely Google-owned project to a new home with the OpenJS Foundation, under a truly open governance model.</p> <p><img src="https://lit.dev/images/blog/openjs/openjs_foundation-logo-horizontal-color.png" alt="OpenJS Logo" /></p> <p>This is a huge milestone for Lit, and it's something we've been working towards for a long time. Joining the OpenJS Foundation as an Impact Project places Lit alongside other critical projects in the JavaScript ecosystem like Node.js, Electron, and Webpack. It's a recognition of the project's maturity, stability, and importance to the web platform.</p> <div class="heading h3"> <h3 id="a-new-era-of-open-governance" tabindex="-1">A New Era of Open Governance</h3> </div> <p>This move is a continuation of Lit's evolution from a single-vendor project into a true community-driven one. Already, all project planning, design discussions, and roadmap decisions have been happening in public, with no Google-only documents or private conversations. Major technical changes are proposed and decided on via a formal <a href="https://github.com/lit/rfcs?tab=readme-ov-file#lit-rfc-process">RFC process</a>, and open engineering meetings are held bi-weekly.</p> <p>Now, as part of this move, all of Lit's assets, including code, documentation, websites, and the Lit brand, are being transferred to the OpenJS Foundation. This ensures that the project's future is no longer tied to a single company. The stability and longevity of Lit will now be supported by a neutral, non-profit foundation dedicated to the health of the open-source JavaScript ecosystem.</p> <p>To govern the project, we are establishing a Technical Steering Committee (TSC). The founding members of the TSC include representatives that work at Google, Adobe, and Reddit, as well as long-time independent project leaders who have been instrumental to Lit's success. This structure gives critical users of Lit a real stake and a voice in the technical direction and management of the project.</p> <p>The initial TSC members will include the following:</p> <ul> <li>Justin Fagnani (Independent)</li> <li>Steve Orvell (Independent)</li> <li>Jim Simon (Reddit)</li> <li>Gray Norton (Adobe)</li> <li>Kevin Schaaf (Google)</li> <li>Peter Burns (Google)</li> </ul> <div class="heading h3"> <h3 id="why-this-matters" tabindex="-1">Why This Matters</h3> </div> <p>We believe this move will be incredibly positive for the Lit community. It reflects the already community-driven nature of the project, but makes it more formal and sustainable. In the past, we’ve heard that some potential contributors were hesitant to get involved with a project that was solely owned by Google. We hope that being a part of the OpenJS Foundation will open the doors to more contributors and collaborators. We're committed to cultivating a vibrant and welcoming community, and this is a major step in that direction.</p> <div class="heading h3"> <h3 id="building-a-strong-community" tabindex="-1">Building a Strong Community</h3> </div> <p>Lit is already the most popular library for authoring web components, and the fifth-most downloaded web framework or web component library on npm, right behind Angular. It's used in a massive number of critical, high-impact projects, from complex web applications to high-traffic websites and cross-framework component sets.</p> <p>Just a few examples include Adobe Photoshop and Illustrator for Web, Reddit, MDN, The Internet Archive, Chrome DevTools and settings UI, Firefox's browser UI, The Microsoft Store, Home Assistant, Web Awesome, and tens of thousands of components at Google across YouTube, Waymo, Google Maps Platform, Labs, web.dev, Colab, Gerrit, and many more projects.</p> <p>A big focus of the project for the last few years, and even more so now that we're in an independent foundation, is to grow this incredible user community into a stronger <em>contributor</em> community, with true community ownership. Creating a vendor-neutral TSC is just one more step on this path. We'll continue to welcome new contributors with more events, documentation, open meetings, and clear workflows; and invite more critical stakeholders to have official representation on our leadership teams. Soon, we'll be putting out a call for our first Lit community manager. Stay tuned!</p> <p>We're especially excited to be part of the OpenJS Foundation's commitment to growing and maintaining critical JavaScript projects like Node.js, Express, Webpack, and Electron, and we share their <a href="https://openjsf.org/about">mission of enabling an open and accessible web</a>. The OpenJS Foundation is providing the Lit project guidance on formal, open governance, project support, community building, and more, and as an Impact Project, Lit will participate in the OpenJS Foundation's Cross Product Council (CPC).</p> <div class="heading h3"> <h3 id="advancing-the-web-platform" tabindex="-1">Advancing the Web Platform</h3> </div> <p>Lit was created in order to help make web standards like web components easier to use. The Lit team has always been deeply involved in the web standards process, working with browser vendors, prominent web standards bodies, and the Web Components Community Group to advance the web platform. Recently, we’ve seen some huge wins, including scoped custom element registries shipping in Safari, CSS module scripts landing in Firefox, composed selection hitting baseline 2025, and the cross-scope ARIA references specification being finalized.</p> <p>While we've always strived to be a distinct voice from Chrome in standards discussions, being an OpenJS Foundation project makes that distinction even clearer. Now, with a diverse TSC, we can bring even more perspectives to the table and continue to push the web forward for everyone.</p> <p>This is an incredibly exciting new chapter for Lit. OpenJS is a wonderful host for us, as our missions to advance the web and JavaScript align so well. We can't wait to see what more we all build together. Thank you to everyone who has been a part of our evolution so far. The future of Lit is bright, and it's a future we'll all build together.</p> <div class="heading h3"> <h3 id="get-involved" tabindex="-1">Get involved</h3> </div> <p>We invite everyone to become part of Lit's developer and user community. Whether you simply use Lit for your projects or are interested in contributing code, documentation, outreach, feedback, or good vibes, there is a way to get involved.</p> <p>You can find more about the project at <a href="https://lit.dev/">lit.dev</a> and by joining our Discord server at <a href="https://lit.dev/discord/">https://lit.dev/discord/</a>. All community members are invited to our engineering meetings that occur every other Thursday, posted on the <a href="https://calendar.google.com/calendar/u/0/embed?src=c_5f73b3899868341aa19ebd1d8fcd2c49b884cfbcbe7f8e655227c5a7905c0692@group.calendar.google.com">calender here</a>. It's a great way to connect with the project and learn how to get involved.</p>