Hacker News new | past | comments | ask | show | jobs | submit login
Lit: Simple, fast web components (lit.dev)
211 points by tambourine_man on July 20, 2023 | hide | past | favorite | 141 comments



Maintainer of Lit here!

A few of the unique things I try to emphasize when talking about Lit because it's so different from a framework:

Lit is just helpers to make web components. It's implementation detail. On the outside the components are just standard HTML elements.

Because of that, Lit makes no assumption that other elements you're using in your components are made with Lit. This low coupling preserves interop, and makes it easy to incrementally adopt Lit, and incrementally leave it if you wish. Low lock-in is an important principle for us.

Because of the low coupling, Lit doesn't have any centralized scheduling, diffing, etc. Each component is its own independent render root and schedules its own updates in microtasks. This has some great upsides - it's very easy to modify scheduling per component, and decouple costly subsections of a page to limit jank.

And we get great performance from the emergent global properties of independent roots. We check for data changes in the property setters for each component, so data updates only cause component updates along the paths in the tree that both use that data and see a change. Then lit-html, the template system, doesn't use VDOM, but remembers where data is bound to the DOM and only updates that if the data changed. It's very efficient.

Also, Lit requires no compiler to toolchain. You can use it from a CDN, or with import maps, or with a tool that resolves JS modules import specifiers. You can use decorators with TypeScript, or not. You can bundle or not. We do have TypeScript and ESLint plugins for working with templates.


Lit is awesome, thanks for maintaining it. I do more Svelte these days but have used Lit in the past and was very pleased with it.

Looking forward to using Lit in the future since I think it does a really great job of getting out of your way and being supremely easy to use and standards-adjacent.

> Because of the low coupling, Lit doesn't have any centralized scheduling, diffing, etc. Each component is its own independent render root and schedules its own updates in microtasks. This has some great upsides - it's very easy to modify scheduling per component, and decouple costly subsections of a page to limit jank.

Could you share some downsides?

> Also, Lit requires no compiler to toolchain. You can use it from a CDN, or with import maps, or with a tool that resolves JS modules import specifiers. You can use decorators with TypeScript, or not. You can bundle or not. We do have TypeScript and ESLint plugins for working with templates.

This is awesome -- thanks for

As for an actual new question, I'd love to know if there are any considerations on shared data in Lit -- with the just-web-components nature of Lit, data & reactivity are hard to fit in obviously but would be very beneficial to solve in a way that is just as easy to use as the rest of lit.

I took a stab at what it could look like and wrote a demo[0] and post[1], but have not kept up with the Lit community since then to see if there's some other solution/pattern gaining steam.

[0]: https://mrman.gitlab.io/services-as-dom-elements

[1]: https://vadosware.io/post/sade-pattern-services-as-dom-eleme...


I've had fun playing with lit+mobx - there's

https://github.com/alexanderweiss/mobx-lit-element

and (documented as based on the former)

https://github.com/adobe/lit-mobx

already out there, and next time I get some Copious Free Time I plan to experiment with adobe's connector plus mobx-state-tree (https://mobx-state-tree.js.org/intro/welcome).

NB: I haven't used the above for anything 'real' yet ... but I do think at the very least it's worth a look to steal ideas from.


This is a pretty reasonable approach -- I guess relying on the platform to supply the same import for the same identifier (URL/file path/etc in the browser) is enough for state, but I really wanted something a bit more declarative somehow...

Feels like almost all of the world is now wonderfully DOM-friendly/not hidden from HTML but maybe it just doesn't make sense to try to make state declarative in terms of the display layer anyway.


In terms of low decoupling:

It sometimes makes working with _slotted_ children in a non-lock-in way difficult in terms of state synchronization as opposed to props.children in React. The solution here in an app would be to use a state manager, but it's much more difficult for components that do not want to require the user to use a state manager e.g. design systems.

Additionally, hydration and customElements.define() upgrade order is a different consideration compared to other mono-state frameworks when it comes to SSR.

In terms of state management:

There are plenty of tools out there like lit-mobx shopped by Adobe. The team has also made some examples that show how easy it is to integrate your own state manager into Lit using ReactiveController such as Redux. There is also work being done such as example implementations of Preact Signals integration:

https://github.com/lit/rfcs/blob/preact-signals/rfcs/NNNN-pr...


Lit is great, one thing I learned from Web development in the last couple of decades is the less layers to debug between browser native support and UI application code, the better.


You have reactive properties to model the internal state of a component but what's the recommended way to manage global state? Example: I click a button in a row of a table and I make something happen outside the table, so several components upward the components tree of the page and then a few others downward in a different branch of the tree.

I'm sure there is a better way to do it but (10 seconds of thinking time) maybe a top component with just an empty div and a reactive property with the global state and the code to apply changes to the reactive properties of the appropriate children components, no matter how far down the tree? That seems something to standardize and not code from scratch every time.


There is a lit context package in lit-labs, which, like React context, can be used for passing the state across multiple layers of components; but I think that, just like with React context, it will not be sufficient if you have a lot of global state. In such a case, some state management library will probably be needed. I don't think Lit has any opinion on what such a library should be. I know some people like to leverage the web platform to its fullest, and just use a class that extends EventTarget for state management (see e.g. https://github.com/thepassle/app-tools/blob/master/state/ind...)


I created LitState for this: https://github.com/gitaarik/lit-state


Thanks, this looks really interesting!

I'm just thinking aloud here based on your description (and note that I'm a backend/data engineer looking to build data apps with no front end experience), would this integrate well with htmx then since each component is independent?

I really like the htmx approach and have been looking for a good visualization component framework that will play nice with it.


Yes it would. Htmx works via attributes on html elements, Lit is just a layer over Web components, and Web components quite literally `extends HTMLElement` :)


Is this the same Lit that started at Material at Google? Not seeing easily accessed references.

Is it maybe no longer associated?


I always had the impression that the relationship was in reverse but maybe this is what you had in mind? https://github.com/material-components/material-web



Lit looks really cool it would be great to see some more examples and starter kits. Perhaps an example of how to build web components for use with other projects that are not Javascript based as well. Bundle up components into individual deployable files for example


Awesome work, thanks for maintaining it! What's the recommended strategy to do unit testing? I tried a couple of months ago to use jest but it gets messy really quick due to poor support for shadow DOM. Thank you!


Check out Web Test Runner [0]. It uses Puppeteer to test in real browsers and is easy to setup. I test in Chromium, Firefox, and WebKit concurrently.

[0] https://modern-web.dev/docs/test-runner/overview/


Out of curiosity, is it possible to define lit-html templates outside of JavaScript, such as in an accompanying HTML file?


Stampino is an experimental system to do just that: https://github.com/justinfagnani/stampino

It utilizes lit-html's compiled template support to transform HTML templates into lit-html templates and reuse the underlying efficient rendering / updating machinery.


I’ve been using lit in side projects (e.g. runno.dev) and really enjoyed it. Just like any framework it can be a bit confusing learning the primitives but I’ve found it as productive as React, Vue or Svelte.

The thing I like most about lit is that it embraces web standards. Sometimes that means the ergonomics are a bit strange. But it also means it gets performance benefits, and interoperability bonuses. Plus it feels like you’re learning something about the underlying platform while you’re using it.

The best example is that it uses reactive data binding via attributes for passing data down the tree, and native DOM events for passing data up the tree. That allows you all the same safety that a framework like React offers, but also means your component can be used by any other framework, or by vanilla JS (because they all support the DOM).


Lit looks really good, I keep trying to find an opportunity to try it out. I feel like web components and the tooling around them has finally got there. Major front end frameworks like React, Vue and Svelt finally also have good support for them.

What I really want is a good set of unstyled web components implementing many of the common UI controls that we all end up either building ourselves or finding an implementation of in our framework of choice. Things like drop down menus, select boxes, and tool bars. They could then be used with any of the common front end toolkits.


Creator of Shoelace [0] here. As someone who’s built multiple design systems and component libraries, I assure you that unstyled (or “headless”) components are often much more time consuming and painful to adopt than those with good default styles.

That said, I commonly find that most folks don’t want unstyled components because it’s quite a bit of work to style every single state of every single component. Most people just won’t do it or, if they try, they don’t do it right and they don’t do it completely.

What many folks do want are components that have simple, generic styles you can quickly tweak to match your site/app using a skill you already know: CSS. (This is something you can do with Shoelace’s 50+ web components already, but we’re working to make it even easier with additional CSS custom properties.)

[0] https://shoelace.style/


Just want to say I'm using Shoelace in two Rails projects and I absolutely love it.

Thank you very much.


Thanks so much for your work, the components look great and straightforward to use. Next time I'm building something will definitely try to give Shoelace a spin.

Can I ask, are ARIA attributes handled by default?


Perhaps this isn't as specific of an answer as you're looking for, as I'm not too familiar with the Shoelace library, but perhaps we gain some insight from the Shoelace Accessibility Commitment.

> My commitment to Shoelace users is this: Everything I develop will be built with accessibility in mind. I will test and improve every component to the best of my ability and knowledge. I will work around upstream issues, such as browser bugs and limitations, to the best of my ability and within reason.

https://shoelace.style/resources/accessibility/index.html


The goal is to handle as much accessibility as possible with smart defaults and by making it easy for users to get right. Currently, all aria stuff is handled internally the components. For example, look at <sl-input> and you’ll see that the input, label, and help text are automatically linked in the shadow root. The minimum the user needs to provide is a label and assistive devices work as expected.


It is very true. Most of us who are not designers just want a very good looking default style. We can change if we want to later. It is a pain that react doesn't come with default style.


At my workplace we only ever used it once to build a skinnable white label customer support widget for about a dozen of our client's websites.

It's a webcomponent that gracefully degrades to es5 + polyfills for IE (this was years ago).

Getting the rollup build to work correctly was a bitch and a half, but it turned out nice and it's still in use today.


Agreed. I get excited to see "headless components" until I read the fine print that it's locked into framework x (usually React). I wish there was a robust headless AND framework-agnostic component library (preferably relying on Lit or Stencil).


Think thing is that Ionic have proven this can work with the massively underrated Ionic Framework (built with Stencil, which they also built). I just wish they expanded a little further into desktop UI components and provided an no/low styled variant - I dislike Material as a base style, it's too opinionated.

They are 50% of the way to building a universal mobile+ desktop ui toolkit.

Do the same with Ionic Capacitor, make a desktop version, and that would be an incredible improvement over Electron - it uses the OS supplied web view.


Nobody wants Shadow DOM though. Using ::part is always clunky and we’re all lying to ourselves when we say “oh no that’s the feature”.

The whole shadcn/tailwind philosophy of having you own your components is the future.


Wait, but that is the feature. My issue with Shadow DOM is that "base" styles (like fonts and colors applied to tag selectors) don't come through, not that I can't override any given style from outside.

I'm not really sure what you mean by "own your own components"?


You don't need to use Shadow DOM though?


I haven't used Lit yet, but have used lit-html standalone professionally for some projects. (lit-html is a very small, very performant library and the templating solution for Lit).

I'm very happy with it. I don't have a use-case for web components (so far) and am happy to just wire up dom events to state changes to lit-html. It requires _very_ minimal plumbing and is very easy to reason about.


unstyled web components: look into ING Lion Web Components (Lit-based) or @generic-components/components (vanilla)


check out @microsoft/fast-foundation. It’s UI primitive web components and works really well with lit.


Been using Lit for a few years now, it just keeps getting better. It does what it does, and stays out the way. Please don't call it a framework though, the best part of Lit is that is basically some (very lovely!) sugar over standards built into your browser. And as browsers keep improving (at an amazing pace IMO) Lit keeps getting smaller, which might be my favorite thing about it.


I've used Lit. For what it is, its pretty decent.

One of my complaints with Lit and others[0] is they're most definitely becoming something of an "Angular Lite". Heavy on decorators if you want developer ergonomics, but yet they embrace none of the advanced toolchain things you get with angular-cli. Due to this, it can feel very clunky to build apps using web component frameworks like this. The community as a whole seems very anti-tooling and I think its to the long term detriment of the ecosystem.

The only exception is Stencil[1] that I can find.

They're also missing first class concerns you get handled with other frameworks, like SSR, compiled templates etc. There's no web component equivalent to Next.js that I am aware of.

I don't like using them for design systems. You bail on your framework of choice rendering model, and that's problematic to me.

[0]: https://www.fast.design/

[1]: https://stenciljs.com/


Lit doesn't require decorators, and if you do use them they only require a pretty standard TypeScript or Babel compile.

Are decorators the only thing making Lit like Angular? Angular is not the only project that uses decorators, and decorators are standardized in JS now.

Stencil is good, but requires a compiler where Lit doesn't.

What tooling are you looking for? We have template type checkers and eslint plugins. Starter kits. Prettier works for formatting...

https://lit.dev/docs/tools/development/


I am aware you don't need decorators, this isn't what I was saying. I said its the only way to use Lit with any measure of good developer experience.

Decorators are not the only thing that make it like Angular. The way templates work, template helpers (directives), controllers are all very Angular like in practice.

Tooling is much more than linters, eslint plugins and starter kits.

Unit & e2e testing helpers, build tools, HMR / dev server support. These all matter too and its important that they keep up to date with expectations of developers in what they expect out of these experiences. Even better when it is all rolled up in a nice CLI interface.

Not to mention it would be nice to have optimized convenience features, like Vue style SFCs for authoring components and templates.

Stencil requiring a compiler is not a negative. It makes it an end to end solution and thats very popular for a reason (Next.js, Nuxt, Sveltekit are all very popular for a reason).

I believe strongly that projects need to provide these things as 1 party concerns. I think the Vue community is proof positive of how strong this can be for the ecosystem.

I'm certain between Google, Microsoft, Ionic, and many others there could be real solutions for all this. After all, the biggest advantage of using web components is they are a shared interface


I'm a bit confused by your examples.

Lit templates and massively different from Angular templates, and more like React templates if anything. All Lit control flow and expressions are just JavaScript in Lit, like React, and different from Angular.

Directives in Lit are just JavaScript function calls you use in bindings. In Angular they are things that get access to the template and contents themselves.

Angular doesn't have a concept similar to Reactive Controllers that I know of. They are more similar to custom React hooks.


To reply to the reply below:

I still don't understand the criticism. Lit template have HTML elements, bindings, and control flow. They're pretty JSX-like just within standard JS syntax. Stencil is the same, but JSX instead of HTML strings.

Do you have any specifics on what the extra boilerplate is to you? What makes Stencil components feel like "components"? Are you just saying you like JSX?


Not how it works per se, its how it feels. I admit this to be a subjective metric, but it felt all kinds of Angular-like when I authored web components. Lots of boilerplate and indirection that I didn't enjoy. Its not the declarative authoring experience I was hoping for.

Stencil was the cleanest to me because components felt like components, and could be interacted with more naturally.

There's just alot of missing pieces. Tooling matters. Ecosystem matters. Developer Experience matters. There's a reason so many people turn to Next.js or Nuxt etc.


Having worked with both stencil and lit for years each, there's very little difference between them in how they operate? Stencil uses jsx, lit uses template literals. Otherwise there's a striking degree of similarity. You could probably convert a stencil component to lit in an hour or so (in fact, I have done this multiple times as I migrated away from stencil).

If anything lit has some additional niceties, a better ecosystem, and less restrictions that gets imposed by stencil's compiler


Sounds like my kind of community as I'm also extremely anti-tooling.

I want to feel like I'm working with native browser features as much as possible. Personally, I would even consider doing a project with plain HTMLElement. If I found that I absolutely needed the convenience of state reactivity, only then I would use Lit.


Stencil does have SSR but requires compatible framework tooling https://stenciljs.com/docs/hydrate-app


Thats why i called it out as an exception to what I've seen otherwise


I took an interest in Lit at one point and I gave up when I discovered that its core functionality is ungoogleable.

At the heart of Lit are components named "html" and "css".

Confusion reigns, search engines cower, beginners try to grasp the conceptual different between html and actual html and css and actual css. You'd think the authors would have gone to the trouble of naming those critical components something like lithtml and litcss to give them a little searchability and to deconfuse them, but it seems not.



Lit doesn't use any special dialect of HTML or CSS. It's just HTML and CSS.


I think they’re referring to Lit naming components ‘html’ and ‘css’ - if you go to the tech docs here the very first example imports ‘html’ and ‘css’.

https://lit.dev/docs/components/overview/

I agree that those are odd choices and the arguments provided seem reasonable I.e. they’re likely ungoogleable, and beginners would be confused.


In Lit `html` and `css` are template tags, not components.

Those names are well supported by editors and enable syntax highlighting. If we named them anything else it wouldn't work without extras tools.


The fact that you are explaining this to me reinforces my point.

One of my primary criteria in choosing a technology to work with its how accessible is community support, documentation, third party articles and writing.

It had better be a compelling technology that names its main things exactly the same as the biggest concepts in web development, thereby making it a battle to resolve questions and issues and adding unnecessary confusion.

I do use a nodejs library called "Postgres" which provides a Postgres SQL driver but I really hate the fact that searching for documentation/issues is essentially impossible. I use it because I feel I had no choice, it's the best possible technical solution.

Names matter.

Searchability matters a huge amount.


So your gripe is essentially you don't like reading the documentation of the libraries you use, just, in general?

Template literals are just a feature of javascript, it's not even anything that bespoke. That's why it's called "lit". The output of those tag functions are just rendered with standard DOM features too.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...


I'm curious. When are you searching for `html` and `css` and not using the https://lit.dev docs, or already reading about them in some way? This is literally the first criticism I'm ever heard of the template tag names.

Did you see a code snippet and want to learn more?

`html` and `css` are just functions we vend. They're important ones, but two among many. The names need to be short and intuitive so that when you see something like:

    html`<p>Hello world</p>`
both the developer and tools know what to expect of the string content. Naming them something unique would really harm readability, IMO.


It’s like complaining that sql library has tagged template function called sql - of course it will and it makes perfect sense.


> It's just HTML and CSS.

It's not, and hasn't been for a long time. It's its own DSL with unexpected constraints on what you can use with it.

  `<some-component 
     attribute="string only" 
     ?boolean=${boolean}
     .property=${any_js_variable}
     @event_name=${callback_function}>
     none of this is "just html"
   </some-component>
  `


Surely just adding "lit" to your query helps narrow down the search.


Just to double-check, "lit html tag" returns pretty good results for me in an incognito window: https://www.google.com/search?q=lit+html+tag


It's not too bad. At least, not nearly as bad as naming your language after the most common English verb of motion, especially when your company is literally Google itself.


I'm impressed by how incredibly low your bar for trying is. It's on par with "There were too many parentheses".


I love Lit! Easy, fast, super lightweight as it's a thin layer over standards-based web components. Using it for all my side projects, as well as stuff at work.

Server-side rendering is still a missing piece. But overall, I'm very happy using it going forward.

And if you need a web component library to pair it with, Shoelace[0] is a fantastic library of prebuilt web components using Lit. I'm loving this stack.

[0]: https://shoelace.style


I think web components were almost a good "built-in" way of doing React/Vue. Where it lost me was the Shadow DOM. I get that it's supposed to encapsulate the contents of a component and restrict JS/CSS to itself, but it's overkill IMO. It's basically like having a bunch of iframes and makes it much harder to query things, which is very much unlike the rest of the DOM. I don't need guard rails to tell me how to do encapsulation.


Encapsulation might be overkill for a single developer, but it very much matters for teams and using third-party components.

If you want to drop in a calendar component into your page from npm, it helps if that component's styles don't leak into the page, and if page scripts don't accidentally mess with component internals.


> makes it much harder to query things

This seems overstated. It’s different but not really harder.

  document.querySelector('my-lit-element').elementIWant;

  class MyLitElement extends Lit {
    get elementIWant() {
      return this.renderRoot.querySelector(...);
    }
  }
Though, maybe one doesn’t like querying twice. I’m not sure of performance implications there, to be honest, but I’d expect it to be negligible in most cases.


I think framing it this way can lead to real gripes with the interface. Web Components are a great way to build individual components that can be reused across an app, website, or shared as part of a library. They are like helper functions for HTML.

They don't work as well for building apps, sure you can do it, but tools like React/Vue/Svelte are much better at building a whole app experience. Particularly when you consider meta-frameworks and the ecosystem around them.


I remember when the language was Web Components would replace frameworks, this was something the people pushing the standards were actively championing at the time and was really one of the main goals of Polymer as well.

They could work well for building apps if the ecosystem was more invested in giving developers what they actually want in a timely manner. (Looking at you template instantiation)

The problem with using them for component libraries is that you break your rendering paradigm of the framework you're using, and that can lead to situations like trying to add event handlers to child components impossible for instance, or having to over-use refs


> I remember when the language was Web Components would replace frameworks, this was something the people pushing the standards were actively championing at the time and was really one of the main goals of Polymer as well.

The language is still there. If anything, it has become more aggressive. Now lit (and stencil) are "standard-based" and "future-proof", and "they are not frameworks", unlike all those non-standards-based framework abominations. (at this point most people roll their eyes).

> They could work well for building apps if the ecosystem was more invested in giving developers what they actually want in a timely manner.

The problem is that none of the people involved in the development of web components ask what developers want. If they ever ask, any answers (including answers from other framework authors and contributors) are ignored, derided, and misconstrued.

There's a reason even people and frameworks who really advocated for web components in the very beginning (Vue, Svelte, Solid) are completely against them now.


I believe the VSCode UI components that are designed to be used both internally and by extensions have React wrappers pre-built - see https://github.com/microsoft/vscode-webview-ui-toolkit/blob/... - and the source code to said wrappers might be an interesting read.


Shadow DOM is native web feature. If you don’t like it you can simply not use it. Lit does not force you to use Shadow DOM


> Shadow DOM is native web feature.

Doesn't mean it's a good feature. This is recognised even by people who push them: https://w3c.github.io/webcomponents-cg/2022.html

--- start quote ---

It's worth noting that many of these pain points are directly related to Shadow DOM's encapsulation. While there are many benefits to some types of widely shared components to strong encapsulation, the friction of strong encapsulation has prevented most developers from adopting Shadow DOM, to the point of there being alternate proposals for style scoping that don't use Shadow DOM. We urge browser vendors to recognize these barriers and work to make Shadow DOM more usable by more developers.

--- end quote ---


poorly designed web components are so painful because of that


Yeah, this is not an issue for very well-designed WCs like https://shoelace.style or in cases where it's not necessary like https://modelviewer.dev/


I dabbled with Custom Elements a while back, which IIRC was essentially the same thing as web components, but without the shadow DOM.


They are two names for the same thing. A Web component _is_ a custom element.


It's trivial to turn it off in Lit if you don't want to use the Shadow DOM.


We absolutely love Lit. We've used it for our Web Components after a brief (bad) dalliance with using Angular Elements to make some.

We pair it with Storybook, finicky though it is, to have a catalog of our components and stories showing off the variances for each.


One scenario for using Lit is with a PWA; it comes pre-built with Microsoft-founded PWABuilder's starter kit:

https://docs.pwabuilder.com/#/starter/adding-content?id=addi...


I mean, if you're going to use web standards, why not just go all the way. Compare to https://legacy.reactjs.org/docs/add-react-to-a-website.html. Preview at https://andrewmcwatters.github.io/custom-elements/. Example at https://github.com/andrewmcwatters/custom-elements:

    // https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements
    // Create a class for the element
    class LikeButton extends HTMLElement {
      static get observedAttributes() { return ['liked']; }

      constructor() {
        // Always call super first in constructor
        super();

        this.liked = false;

        // Create a shadow root
        /* const shadow = */ this.attachShadow({mode: 'open'});
        this.render();
      }

      get liked() { return this.hasAttribute('liked'); }
      set liked(state) { this.toggleAttribute('liked', Boolean(state)); }

      attributeChangedCallback(name, oldValue, newValue) {
        this.render();
      }

      render() {
        const shadow = this.shadowRoot;

        if (this.liked) {
          shadow.innerHTML = 'You liked this.'
          return;
        }

        shadow.innerHTML = `<button onclick="this.parentNode.host.liked = true;">
      Like
    </button>`;
      }
    }

    // Define the new element
    customElements.define('like-button', LikeButton);


People do this and it's fine!

Lit's just there to help once you handle more features and corner cases, and do this for 10's to 100's of components.

We're hear numerous times from developers who start with raw web components that the started to put common functionality into a base class, expanded their base class, then realized they were building a clone of LitElement, so switched to Lit.

That's fine too! Leaning on common, well-testing implementation is great, and being able to switch to it seamlessly is one of the benefits of web components.


I think a lot of people would still prefer to write and read the Lit version of that <like-button> too: https://lit.dev/playground/#gist=25ef7a5ea9b73406b4418ba59cf...

    @customElement('like-button')
    class LikeButton extends LitElement {
          
      @property()
      liked = false;
    
      render() {
        return this.liked
          ? 'You liked this.'
          : html`<button @click=${() => this.liked = true}>Like</button>`;
      }
    }


To make that a fair comparison Andrew his native code should be refactored to: https://jsfiddle.net/WebComponents/ovtc5wpx/

    customElements.define('like-button', class extends HTMLElement {
      static get observedAttributes() {  return ['liked']  }
      get liked() { return this.hasAttribute('liked')  }
      set liked(state) { this.toggleAttribute('liked', state) }
      constructor() {
        super().attachShadow({ mode:'open' });
      }
      attributeChangedCallback() {
        this.connectedCallback();
      }
      connectedCallback(){
        this.onclick = (evt) => this.liked = !this.liked;
        this.shadowRoot.innerHTML = this.liked ? '<b>You liked this!</b>' : `<button>Like</button>`;
      }
    });

Now, a shadowRoot is a bit wasteful here, as inheritable styles *will* style shadowDOM.

So we remove shadowDOM:

    customElements.define('l1ike-button', class extends HTMLElement {
      static get observedAttributes() {  return ['liked']  }
      get liked() { return this.hasAttribute('liked')  }
      set liked(state) { this.toggleAttribute('liked', state) }
      attributeChangedCallback() {
        this.connectedCallback();
      }
      connectedCallback(){
        this.onclick = (evt) => this.liked = !this.liked;
        this.innerHTML = this.liked ? '<b>You liked this!</b>' : `<button>Like</button>`;
      }
    });
To do that in Lit, you actually have to *ADD CODE*

    createRenderRoot() {
      return this;
    }
Making the Lit code LONGER than the Native code

    import {html, css, LitElement} from 'lit';
    import {customElement, property} from 'lit/decorators.js';
    @customElement('like-button')
    class LikeButton extends LitElement {
      @property({type: Boolean, reflect: true})
      liked = false;
      render() {
        return this.liked ? 'You liked this.' : html`<button @click=${() => this.liked = true}>Like</button>`;
      }
      createRenderRoot(){
        return this;
      }
    }
In real live projects you won't be nitpicking about these bytes and the 6K library/BaseClass Lit adds. Or the 7K lit-element.

Or would you? When those bytes are added for each! component if you develop truly self-contained web components...

Most Web Component Developers are still building Apps _with_ Components, not Apps _made of_ Components.

When doing Native you will *ofcourse* develop your own *BaseClass* (like Lit is) And for 95% of your time you will just be doing Plain Old JavaScript code.

Most Litters don't have a clue what is going on under the hood.

Most Native developers just silently do everything native, they are not the type to evangelize their choice on Social Media. Their code will run without any issues, upgrades, or breakin changes, for the next 25 JavaScript years


Thank you to both of you for posting your different takes!


I created some libs for Lit to make things easier:

LitState: Shared component state management - https://github.com/gitaarik/lit-state

LitStyle: Shared component styles - https://github.com/gitaarik/lit-style

LitDocumentEvent: Global event handling - https://github.com/gitaarik/lit-document-event

Also check out "Lion" from ING, which contains all kinds of handy components that you can use and configure and style to use them in your app: https://github.com/ing-bank/lion


When I write HTML/JS, productivity and convenience for me means the ability to easily style and not reinvent:

a) Select dropdowns as feature-rich as select2 (search, style, custom click handlers, custom appearance in box, multiselect, callbacks)

b) Data Tables as feature-rich as jQuery DataTables (search, sort, paginate, w/ server-side data, callbacks)

c) A high-quality, customizable charting library that's interoperable with the components

d) A slider / carousel / swiper that's as feature-rich as swiper.js

e) A sane and typical component library (ideally from one place like Ant)

I don't build libraries, I want to use them to build applications, and I don't want to spend too much time re-inventing them or making them play nice with each other - i.e. figuring out when one of them is done initializing so that I can trigger the "initialize" of the other and so on.

The solutions thus far range from some compilation hellscape where I have to write everything in a custom dialect, which then gets compiled to HTML/CSS/JS and then I have to debug things cryptically because it's generated code.

The other end of the spectrum is something that's lightweight and uses the platform extensively like htmx or what lit appears to be positioned as.

I've written production applications using Angular, React, Vue, Alpine and it seems like the newer the library, the less likely it is to have an easy way to support the large selection of component libraries you could just throw together and they "just worked" in the days of jQuery + something. As a result, I end up having pages that are still jQuery + something because neither my users nor my customers care about these details, and the tradeoff is minor.

As a developer it sure would be nice to have a dx where you didn't have to reinvent these things or work with ancient libraries.


Lit is there to help you write web components, so if you don't want to write components it's not a big help, and that's ok.

The flip side is that you should ideally be able to find pre-made web components that fit your need, like I think you're asking for. There are a lot of components out there, which you can hopefully find with enough diligence. What's missing is a great comprehensive catalog of components. Something I've tried to work on, but it's hard to find enough time or funding to complete.


Agreed - components typically exist in various states of feature-richness, and invariably you end up finding an almost-perfect one, if you do.

They also sometimes sit abandoned and unmaintained.

Some catalogs use ratings/votes but they aren't a good heuristic to factor in these two details.


Do you really need jQuery though? Pure JavaScript is viable these days.


My needs are usually secondary to the library's dependencies.

I'm more than happy writing vanilla JS for my own event handlers and components. I don't mind adding a small library like alpine either to make the click handlers etc easier to write.


I have no clue what web components are and at this point I am afraid to ask.

Probably something to take up with ChatGPT at some point.


You can define your own html components. Let's say <input/> didn't existed, you can create your own with web components.


It's a way for you to define your own custom element with encapsulated behaviors and styling.


I'm not saying for one moment that it matters but one thing I was really surprised to learn was that lit (16.6kb) is actually larger than preact (11kB). With it taking advantage of Web Standards so well, I expected it would have a big advantage to be much smaller.


Lit is great, really easy to grasp and to use.

One thing I don't understand in lit (or vuejs, svelte etc...) is why we can't have an each loop that would use information about what has changed.

In my most common case, I am simply updating an item in an array (or removing/adding an item) and the each loop could use the list of operations to do the changes instead of iterating over all the items.

For large array (1000+ items) for a SVG diagramming tool, performance would be much improved, no?


Seems like it lacks support for SSR? I'm wondering if it's ready or make sense to replace web framworks or what is its optimal use case


https://lit.dev/docs/ssr/overview/

SSR support is coming along. It's taking a while because we're trying to do it in an interoperable way, both to allow mixing of web components from different libraries, and to plug into framework-specific SSR (There are Lit SSR plugins for Next and Nuxt available).


I was looking for comparison and found this post

https://webcomponents.dev/blog/all-the-ways-to-make-a-web-co...

Which puts 61 of web-component libraries side-by-side. Sadly my favorite, RiotJS, is not on the list.


> Sadly my favorite, RiotJS, is not on the list.

Looks like it might be in the "Wrapped into a custom-element" category.


The most recent episode of JS Party (284) is on Lit.

I highly endorse this podcast, but I have not listened to this one yet.

https://changelog.com/jsparty/284



One thing I don't get, is how can you use global icons libs like fontawesome, in your lit components.


I believe you would simply return an html template with an i tag that has class="fa-solid fa-magnifying-glass", for example


The italic tag is not for icons.


The i tag is used for icons in fontawesome. https://fontawesome.com/icons/file?f=sharp&s=regular


Yes I know. The italic tag is not for icons.


Doesn't works, probably due to the shadow dom ?


Does anyone know if the social icons on that site are from a set somewhere?


I worked on adding some of these. We pull them from each of the company's respective brand identity page + some manual SVG cruft elimination to decrease code size.


class ... static ... constructor ... super ... this ... extends ... @. Give me a break. I thought we'd moved on from Angular's attempt to turn the front-end into Spring.


You can just use their templating library lit-html (I have in several projects now) and manage events and state yourself. It's extremely convenient and lightweight.


Defaulting to v2 instead of v3 for the documentation selector in the upper right seems odd, especially considering the extent of the changes.


v3 appears to be pre-release version? Surely that makes sense to not default to pre-release code for the docs?


The upgrade is claimed to be seamless when running Lit 2.x with no deprecation warnings; defaulting to deprecated API documentation is a bit counterproductive.


v2 documentation is not deprecated. v3 isn't released yet.


If v3 is "not released" then having it accessible with the other 2 releases is contradictory - this "prerelease" is still a form of release; no claim was made that the entirety of the v2 documentation was deprecated.


> no claim was made that the entirety of the v2 documentation was deprecated

> defaulting to deprecated API documentation

I am not sure what point is being made here. This seems to be splitting hairs.

Regardless, it makes sense to default to the docs for the version which is considered to be officially released. That version is probably most likely to be used in a production application, which is usually what the docs are intended to support.


We'll switch the default over to v3 once v3 is out of prerelease.


> Tiny footprint, instant updates

I can see that, the website re-renders only three times on load (text - image - fonts).


"skip the boilerplate" but it's an npm package requiring a build system (:


not a frontend guy,is this more of jsx or htmx? what is it's major selling point? thanks


Web components are already built into the browser. Lit is like a wrapper around those.


Lit in a professional setting was a profoundly negative experience. Ooof.

Just use Angular or React or one of whatever the top 3 things are right now.


I couldn't disagree more. We are a professional setting and have an app that is ten years old at this point that has used them previously and is expanding the use of them, not contracting them. This is after using Angular for a long time (we actually use our Web Components from Angular).

I would say starting a new application in 2023 based upon Angular or React would be the Ooof thing to do.


Do yourself a favour, try https://hilla.dev with Lit Components :)

Such a joy.


Sounds pretty lit, Edit:Dang you guys really hated that


Yeah, jokes are touchy. People commonly feel that it detracts from interesting conversation. In practice, there are sometimes “allowed” jokes; otherwise timing it later after the post at least garners fewer downvotes.


The best part is I made that comment an hour after the post and was the second overall lol


That’s a good point. Perhaps “after the conversation” is more accurate, though harder to define. Still, it got a chuckle out of me.


I agree with the after the conversation point. And as long as one person chuckled the downvotes are worth it.


There's nothing simple about custom-html element defined by javascript. It may be "Interoperable & future-ready" but it sure isn't interoptible with pretty much everything from 1995 to 2019.


This is just plain wrong. Web Components work in every browser that matters. They are standard DOM elements and can be written in plain HTML server-side or via legacy front-end libraries.

I'm using web components in production to help interoperability between 2012 era Handlebars/jQuery/Backbone and modern tools like React and Prosemirror.


Until you want to make a form. Look at ING's Lion components or Microsoft's Fast components. Thousands of lines of code to make form/input/button components work as you'd expect them to.

General browser support is good though. Debugging ShadyCSS in IE11 was a nightmare.


>Web Components work in every browser that matters.

Reading between the lines here I'm getting the feel that this is actually, "Web Components work in every browser that people use to spend money." And I don't disagree. If you're doing something for work and being paid to do it then by all means use web components. The large number of people around the world you exclude weren't part of the demographic you were going to get money from.

But saying that it works in every browser that matters is wrong.


What browsers do web components not work in that you would like to see support them?

I think "every browser that matters" means, yes they don't work in IE or legacy Edge, and maybe don't work in Servo or Ladybird, but they work in Firefox, Edge, Chrome, Safari, Opera, etc.

https://caniuse.com/custom-elementsv1


Safari seems to have a caveat.


The "caveat" is that Safari doesn't and will not allow subclassing built-in components.

Note that Safari has opposed subclassing built-in components since the very beginning: https://github.com/WICG/webcomponents/issues/509#issuecommen...

Just a few of the reasons: https://github.com/WICG/webcomponents/issues/509#issuecommen...


Looks like a won't-fix stalemate so why the hype about web components?


Because it was pushed and is being pushed primarily by Google and its devrels. After 12 years in development they are barely usable, have a ton of issues that are not resolved [1] and [2], and any client library in the same state would be laughed out of the room by anyone.

However, there are now hundreds of millions of dollars of sunk costs, dozens and dozens of specs, unbelievable complexity that infects all other actually useful specs (like Scoped CSS which cannot proceed properly because effing Shadow DOM), extreme zealotry and complete unwillingness to engage with anyone even mildly critical of web components.

All this results in a strong desire to keep going and promoting this even if no one can even say what the "done" state is for them. Or what is the actual goal, since that goal changes every few months.

[1] https://twitter.com/Rich_Harris/status/1198332398561353728 None of these have any satisfactory solution (for some not even on the horizon)

[2] Even the people pushing this stuff realise how many issues they have: https://w3c.github.io/webcomponents-cg/2022.html See how many of those are not even close to even being discussed


Sorry, I responded to the wrong person.


web components are standard, and have been for a long while. Virtually no one uses lynx, and it's not anyone else's fault that lynx has lagged on implementing long-existing web standards.


If anyone gets here confused, I left this comment above because I mistook who I was replying to:

I’m curious: does it work in Lynx[0]? I assume no because there’s no executed javascript, which is required to register the component as far as I know.

It’s worth stating the point in a different way. Even one person using such a browser “matters”, in a way, and it’s good to be kind when one can.

(Apologies if this comes off as harsh; however, it does seem to me that the other commenter has a point, at least in their second comment.)

0: https://en.wikipedia.org/wiki/Lynx_(web_browser)

----

“Virtually no one” does sound a lot like someone. Per this point of “browsers that matter”, many people will also say “accessibility matters”. Support of Lynx is a worthwhile goal in regard to web accessibility, in no small part because it does not execute javascript.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: