Hacker News new | past | comments | ask | show | jobs | submit login
The Power of Web Components (hacks.mozilla.org)
170 points by lainon on Nov 15, 2018 | hide | past | favorite | 76 comments



This is a bit off topic, but I really wish the idea of including HTML imports (https://developer.mozilla.org/en-US/docs/Web/Web_Components/...) was taken seriously. There's a lot of people that just want to make a simple HTML site with templates for things like the navigation menu, without a bunch of nasty JavaScript goop that can't be search indexed easily, and the ability to include simple templates using HTML would have been an huge resource for those people and for search engines.

I think it really shows how much of a bubble the web often lives in now. We used to be able to just make a solid web site with simple HTML and a text editor. I shouldn't need to be an extremely hardcore JS programmer or use a crazy static site generator or overengineered LAMP backend to do basic things like reusing HTML and other things that could be largely accomplished with just HTML itself.


HTML Modules are the spiritual successor to HTML Imports that work with the standard JS module loading system: https://github.com/w3c/webcomponents/issues/645


For those following along at home, the reason why you don't need HTML Imports once JS Templates and Modules exist is because HTML Imports are not usable without JS! So you can implement a more elegant solution yourself with a couple lines.

Let's assume you want to use 3 different HTML templates on a page (the html content doesn't matter much for this example).

Here's the example usage of HTML Templates from html5rocks.com:

  <script>
    function handleLoad(e) {
      console.log('Loaded import: ' + e.target.href);
    }
    function handleError(e) {
      console.log('Error loading import: ' + e.target.href);
    }
  </script>
  <link
    rel="import"
    href="example1.html"
    onload="handleLoad(event)"
    onerror="handleError(event)"
  />
  <link
    rel="import"
    href="example2.html"
    onload="handleLoad(event)"
    onerror="handleError(event)"
  />
  <link
    rel="import"
    href="example3.html"
    onload="handleLoad(event)"
    onerror="handleError(event)"
  />
  <script>
    function importHtml(selector) {
      var content = document.querySelector(selector).import;
      var el = content.querySelector('.warning');
      document.body.appendChild(el.cloneNode(true));
    }
    
    importHtml('link[href="example1.html"]');
    importHtml('link[href="example2.html"]');
    importHtml('link[href="example3.html"]');
  </script>
Now let's compare the same feature with ES6 Modules and Templates using a `helper.js` file.

  export async function importHtml(url) {
    try {
      let res = await fetch(url);
      let html = await res.text();
      let template = document.createElement('template');
      template.innerHTML = html;
      let el = template.content.querySelector('.warning');
      document.body.appendChild(el.cloneNode(true));
    } catch (e) {
      console.log(`Error fetching html: ${url}`);
    }
  }
Then we can import the modules on the page in a very clean way...no HTML Imports spec here.

  <script type="module">
    import { importHtml } from './helper.js';
    importHtml('example1.html');
    importHtml('example2.html');
    importHtml('example3.html');
  </script>
My point is that you don't need HTML imports and you'll have to use JS even with HTML imports so just use JS all the way :)


That seems like a lot of trouble to replicate the already built-in ability to import external JS and CSS files.


> We used to be able to just make a solid web site with simple HTML and a text editor. I shouldn't need to be an extremely hardcore JS programmer or use a crazy static site generator or overengineered LAMP backend to do basic things like reusing HTML and other things that could be largely accomplished with just HTML itself.

None of that functionality has gone away, has it? A lot of what a static site generator is doing is saving you copy-pasting a bunch of HTML across files, by giving you templates for common functionality. But you still end up with plain HTML files, and you can certainly get there by editing them all by hand in a text editor.


I think you missed his point, he wants to be able to compose html without having to resort to a programming language.


Easy, configure Apache to serve Server Side Includes, the feature is still there.

https://httpd.apache.org/docs/2.4/howto/ssi.html


Why should we need to do that? We don't have to do that to import external JS and CSS files.


I know. It's pretty shocking that we can load external CSS and JS files, but not HTML files.


XML stylesheets can be used for that (and for more complex processing as well). Though it may be a better idea to apply those before publishing, for the sake of compatibility (and then it's just static website generation).


Ah, back in the day when the major browsers all supported XSLT stylesheets, it seemed like the obvious way forward.


The ability to have the browser request markup for inclusion via URL in the same way it does images is a longtime wish of mine. There are some potential security issues... most of which we have anyway with the approach that requires JS in order to import content from another URL, and having a simple way to pull in document fragments would do away with a good chunk of the things we've had to have a CMS or site generator to do.


This sounds a lot like ASP.NET with Razor. Split out the pieces into Razor partials and dump them in where needed with Html.Partial().

I haven't really had much chance to play with it, but the newer Razor Pages are probably an even easier way to build a simple website.


You don't need to go nearly that far at all. Let's go back in time.. ah.. server-side includes[1]! Problem solved, and we didn't need anything more than a web server.

Being able to do this client side with no code? Yeah, would be nice :)

[1] https://en.wikipedia.org/wiki/Server_Side_Includes


I just use cpp to #include files. Granted, it's barebones and not very extensible.


Totally agree. A lot of simple brochure sites could be done that way.


I really hope that web components take off, because I'm getting pretty tired of having to learn different ways of building components every damned year. Most components don't need blazing-fast rendering engines, the templating engine of the now, or even two-way bindings out of the box, and thus I'd like to use components that can live on their own but also be easily wrapped into whatever framework I'm using.

I'd like frameworks to be a lot closer to scaffolds, or actually be frameworks, as opposed to what most of them are now which is reimplementations of application units. The web components standard can help make it possible for tools to become interoperable between frameworks(okay, and view libraries), that would be wonderful.


Web components work very well in isolation, and/or within a homogenous web component framework/library.

However, it is still pretty challenging to pass data throughout web components (in a way that allows you to build a complete application). HTML attributes are not great for data transfer (string serialization for everything). JS properties are a bit opaque (not represented by markup). And everyone ends up wanting some sort of property binding system, which may be unrealistic to standardize.

I think there will always be a place for some amount of framework/library support necessary for application builders.


Oh I definitely agree. I'm not at all proposing that components make frameworks obsolete. It's just that I would like a future where the Web Component standard becomes the first answer to the frontend development question before moving on to more specialized solutions. Existing frameworks and Web Components would go hand in hand.


Yeah, the way we use web components at Mixpanel involves sticking to the vanilla APIs for lifecycle management, but we still need libraries to handle inter-component communication, state and rendering (see my discussion at https://engineering.mixpanel.com/2018/06/12/making-web-compo... and https://github.com/mixpanel/panel). I do hope some of these concerns eventually get addressed in the standards though.


It's quite easy to pass properties between elements and build entire apps out of Web Components. Many have been doing it for years.

Yes, it requires not just using plain markup - but template systems or JSX+VDOM are really good at this, and there's a huge choice in libraries. SkateJS is a library that allows you to plug-in several renderers to build components. LitElement uses lit-html. Polymer, Svelte, Vue, and Angular (the last when compiled to Custom Elements) have their own...

There also is a chance at standardization with the Template Instantiation proposal from Apple.


If it helps set context, I got my perspective as a developer on the Polymer team


Hi Ian, I know. :)


> HTML attributes are not great for data transfer (string serialization for everything).

You can JSX (as first introduced by React) to pass objects to Web Components. See: https://github.com/wisercoder/uibuilder


Same here, best of all if we start getting Web IDEs built on top of Web Components provinding a Delphi/VB like RAD experience.

Yeah, I know there are a comple of startups attempting to get a foothold on this, but it is still very hard to gain momentum, it seems.


I think the browser dev tools (esp. Chrome's) show some promise in that regard. For instance with Workspaces you can mess around in dev tools and save changes directly to your source files; with a tighter integration between the element inspector, source view, and js console they could achieve some real visual programming power there (for instance being able to jump from a component rendered in the UI directly to its code and representation of current state).


Have you ever been an actual end user of one of those Delphi/VB RAD crapplications that were so easy to build?

I think your goal is very misguided. They all sucked, and were basically no better than MS Access forms.


Yes I have, Borland's common controls dll were quite easy to recognize.

Not everyone was doing Access style CRUD entry forms.

However I have seen a couple of nasty VB.NET apps written by weekend programmers at a research lab, just because they knew a bit VBA.

And while they were nasty, they still made them more productive than before, without being stuck waiting for IT support.


I was trying Polymer as a components library along with React (with react-polymer, and a bunch of glue code). That way the React code amounts, indeed, to a layer of scaffolding saying "render this component here with this data from here." It was wonderful, since to me it felt much more like working with a real UI toolkit, and the only part of React I needed to deal with was the part of it that's actually good. The thing is we already have that abstraction with all of the HTML form widgets, even mirrored in React proper, so _why not_ provide a similar interface around dialogs, progress bars, buttons and menus instead of spitting out gobs of div tags everywhere?

There is a bit of trouble here where different components don't always have a consistent interface, which kind of ruins the "yay, I don't need to think about how buttons are implemented!" thing, but sticking within Google's core library was mostly working out okay. Not sure how it would have panned out in the future, but my sense at the time was we just need some richer widget libraries that include layout components and it'll end up feeling pretty slick.

Alas, nobody else on the team was all that interested in reinventing the wheel, so it's a normal React app again. (This is a good thing, really). But I thought it was a nice taste of the sort of cleanliness we could get with web components.

Edit: Here's where I got, in a now-orphaned commit: https://github.com/pg-irc/pathways-frontend/tree/80fd61cf1f9.... It was the wrong direction, but I thought it was pretty cool :) (And, incidentally, that there is a really cool open source project if anyone's looking for something warm and fuzzy to contribute to).


I took a look at your code, particularly the src/js/ui-components/LinkButton, and that's a lot like what I've been doing in an Ember project, only using a mixture of Polymer and Material Components Web.

Why do you say it was the wrong direction? Just curious. Is it because you ended up using React Native?


Oh, I was happy with it technically, and I'm glad you're doing something similar with some success! It was just the wrong direction there because it added some friction, building new things where we don't need to build new things. For a personal project, I would still be doing it that way :)


> I really hope that web components take off, because I'm getting pretty tired of having to learn different ways of building components every damned year.

I feel like this is a gross exaggeration. You would have had to learn a maximum of two, of which the dominate ones have been around for years now.


WebComponents only solve the problem of creating independent, self-contained functional units for the web. They don't fix all the other issues modern framework stacks try to fix like state management, change detection, two-way binding, inter-component communication/data passing etc. Thats why I don't see the framework soup (Angular, React, Vue, Ember, Aurelia) going anywhere in the near future. Maybe the "component" part will converge in the frameworks towards WebComponents but all the other bits and pieces the framework stacks ship will remain.


I believe Home Assistant's new fancy UI codenamed "lovelace" is based on web components: https://www.home-assistant.io/lovelace/

This should give you a sense of the power of web components.


It's weird that the default behavior when appending a template is to not clone it requiring an additional clone call

>>template.content.cloneNode(true)


That's the default behaviour when appending a DocumentFragment or a Node, and has been since 1997.

The template is just a container for the DocumentFragment, the template content still behaves like any other DocumentFragment always would have, so changing behaviour would be pretty crazy.


I'm not such a fan of how spread out everything is. I'd really like to see html, js, and css all together in one place. React is the best I've seen, but it doesn't provide a good solution for css.


Check out LitElement. It lets you define everything in one place, and because it uses Shadow DOM, CSS is handled as well.

Here's where we'll be with plain standard JavaScript once class fields and decorators land:

    import {LitElement, html, property, customElement} from '@polymer/lit-element';

    @customElement('hello-element')
    class HelloElement extends LitElement {

      @property() name = 'World';

      render() {
        return html`
          <style>
            :host {
              display: block;
              background: blue;
            }
            h1 { 
              color: white; // scoped to the ShadowRoot
            }
          </style>
          <h1>Hello ${this.name}!</h1>
        `;
      }

    }


> I'd really like to see html, js, and css all together in one place.

You mean like Vue components? I think HTML components go on the same line, although this article does not emphasizes this.


Try styled-components:

https://www.styled-components.com/

Makes handling CSS in react a pleasure.


I put together a micro-pattern for working with WebComponents that I really wish were cross browser compatible as it is. It works in Firefox and Chrome and it is partly how I wish the web would move forward.

There is no technical limitations to making encapsulated portable pieces of html, css and js, yet it seems a very uncommon practice to make libraries of small re-usable components, even if they are boutique to you or your company. I think that is partly down to how we go about specing out and producing websites, and partly down to the fact that many don't realise you can already do it.

https://polylab.co/projects/polyblocks.html

An important part of that is well encapsulated CSS, and theming on top of that, something I have written a little bit about as well.

https://polylab.co/articles/ccm-contexts-and-components-css....


caniuse shadow components:

https://caniuse.com/#feat=shadowdomv1

So not Edge (I loath testing MSEdge - always finding new bugs in it - yesterday the F12 development tools crashed even on a blank page -- needed an opaque powershell script from MS to fix it...)


Amazingly, Shadow DOM does not block all outside CSS. The * properties leak in, unless you add #container { all: initial; } inside, but that doesn't work in Firefox. I wonder why authors forget this strange fact.


I don't think it's very strange. It's extremely likely that you want to inherit the default inherited properties like color and font-family. Otherwise Web Components would look out of place on the page by default.


I could be totally wrong here as I am not an expert in frontend, it seems Google has been the loner pushing web component(polymer,etc). Mozilla was lukewarm about it. Something changed or did I miss something badly?

Vuejs has its own web-component(non-standardized), so does React. If browsers can provide native web-component support that will be really nice.


I work at Google and can confirm that we are very much pushing web components and Polymer / lit-html.


Web components may give power to developers but they take it away from users. Any page made with web components is hostile to user styling. I'm surprised Mozilla would support them.


OTOH for me (another freakish web user who does unusual things with the web), web components may make it easier to scrape the website. Developers will be passing data into a component in some way, JSON atrtribute, or a nicely defined data in a property, so it will be easier to scrape and understand via devtools DOM insepctor.

Insteaed of a soup of deeply nested divs, there will be nicer and more meaningful structure of web components.


The move to single page apps have definitely surfaced a lot of JSON-speaking api endpoints that make scraping for data a thing of the past. A great thing for the web, I think, whether or not the site owners are aware!


Weren’t user stylesheets removed from [1] / never present in most browsers?

[1] https://src.chromium.org/viewvc/chrome?revision=234007&view=...


I use GreaseMonkey/TamperMonkey, but WebComponent even make modifying a page using dev tools hard.

Edit: e.g for printing or to make reading / using easier.


They are still in Firefox, but hidden from the user.


there seems to be something in mac safari for 'stylesheet' loading under 'advanced' preferences. if the browsers don't give people tools to edit/manage from within the browsers, even the average tech-savvy user won't bother with these, which is a bit of a shame.


Hello! Author here. I'm a fan of web components for widgets and embeddable third-party interfaces. I'm not as much a fan of them to wrap a site's primary content, for both accessibility and user styling reasons.


Hi!

I'm not a fan of them for web apps that use excessive whitespace between repeating components[1]. Previously you could just edit the global stylesheet in dev tools but now that only changes the current component.

Edit: I get the widget / embedable use case but fear that it won't just be used for that.

[1] e.g. Chrome's new material design bookmarks manager that shows far less bookmarks per page than the old design.


Great write up. Can a web component author create one in such a way that the inner shadow dom styles ARE editable/styleable by the outer or person implementing the custom component?


Yeah, I have the similar need. I want to use <slot> mechanism, so I need shadow DOM, but I'd like to re-use styles, so that they don't need to be copied to each instance of the component. Aside from complicating things, it seems wasteful. It should be possible to use styles from the document's CSS to style the innards of a web component.

I'm still learning, and I'm still missing solution to this.

I know about var(--custom-prop), but that's limited, and still doesn't help with the waste of useless duplication of styles.


What I've done is kinda standardized the solution. I've made all my elements listen for a template tag in the html page that contains <link> tags to the stylesheets I use globally.

<template id="x-global-styles"> <link rel="stylesheet" href="some/sheet.css" /> </template> Kinda like that.

You can use prefetch in the main header to get all your styles in one shot, before page load, if you want.

Then I make my element, if the template is found, pump the innards of the template into itself so all my styles are available.

I use it in conjuction with tailwind so I can write atomic classes and include my atomic css with every element I desire.

From what I can tell, for the most part, my styles don't get reloaded every time. I could be wrong. They seem to get prefetched, if I use a prefetch, or loaded once, then cached. It seems that no matter how many elements I have on the page there are no external calls to get the stylesheet every time. One and done.

Correct me if I'm wrong here. It's just something I fiddled around with.


Very interesting! Thank you. I didn't realize you can use <link> inside web component. But it makes sense!

I read some more, and I reaized that it's probably meant to be that every component has its own small piece of CSS independent of the rest, so that you can use :host, and all the other trickery and so that least amount of CSS per component needs to be parsed and processed.

So I ended up writing a small pre-processor, that converts sass files into a js file with a variables containing styles for each component (like BUTTON_CSS, DIALOG_CSS, SPLIT_LAYOUT_CSS). I just hope that there's some optimization in the browser, such that when the same <style> content is used in multiple instances of the component, it is parsed/processed only once and the results cached for the other instances.


Not currently, but in future Shadow Parts [1] will enable this

[1] https://drafts.csswg.org/css-shadow-parts/


Note: ::part() is currently behind a flag in Chrome.


You can still probably override attachShadow to ignore the argument, and make shadowRoot always open and then use that to modify the <style> inside shadowRoot.

More complicated, but probably doable (with greasemonkey).


It seems like the * CSS selector would still apply to these new elements? And in js things like el.children? I wonder if user styles via something like Stylus[1] could style them also? Now that I think about it, it seems like some of the worst (and most likely) applications will be advertising (to try and avoid blockers).

1: https://addons.mozilla.org/en-US/firefox/addon/styl-us/


How many users apply their own style sheets? I remember this was popular among a relatively few people, and now I don't know anyone who uses things like Stylish or Greasemonkey/Tampermonkey anymore.


User applied stylesheets are fairly uncommon, but then again, so is using a screen reader. Both are essentially a kind of accessibility tech, and when it comes to accessibility questions, the chief concern isn't necessarily whether everyone uses it.

It's probably worth noting that reader-mode -- another accessibility tech -- does seem to be fairly popular.


> and when it comes to accessibility questions, the chief concern isn't necessarily whether everyone uses it.

I wish more developers had your perspective.

My Dad uses Windows' high contrast mode. It's less that "literal dozens" use this feature and more that this feature transforms all that desktop-shaped-material into a computer for the vision impaired.

Isn't the biggest performance enhancement the transition from not-working to working? I view accessibility as the ultimate performance enhancement for a given slice of users.


Some companies care. Most don't. Unless a feature is used by double-digit percentage of users, it'll be axed. It's a sad reality of today, and no, I don't buy the arguments about saving development time, not when said by the same people who also say they want to deliver value to users (as opposed to extract value from them). Because somehow, feature cancellation always seems to touch the features that enable users to unbreak things or optimize their experience.


Delivering value to only 0.1% of users is equal to taking away value from the other 99.9% of users. You're not strictly saving development time, you're reallocating it to better utility.

Now, if those 0.1% of users have some sort of legitimate accessibility issue, we can talk about it. If they just have highly idiosyncratic preferences about their user experience, the axe it shall be.


I'm not sure 0.1% is an accurate reflection of the portion of users with some accessibility issues.

Moreover, whatever the portion of users who currently have accessibility issues is, the portion who will have some is much much larger.

Finally: human accessibility frequently seems to dovetail with machine accessibility. Engineering done with accessibility in mind seems to be less likely to result in silos and more likely to present an interface more amenable to automated interaction.


> Both are essentially a kind of accessibility tech, and when it comes to accessibility questions, the chief concern isn't necessarily whether everyone uses it.

It's still a question of whether a significant amount of people use it within the affected group. If you need to enlarge or increase contrast, there are standard accessibility tools for that which don't rely on HTML at all.


Now if only I could apply user styles to about:reader again, like I could before WebExtensions. Then I could make reader mode’s dark mode use an actual black background instead of an only-moderately-dark grey.


I have developed and maintain what started out as user stylesheets but are now user scripts that improve certain third-party tools we use internally. The one for our support ticketing system is deemed invaluable by most, having turned what was a fairly- to very-painful-to-use system into a moderately pleasant one. Some of the modifications it makes are fairly radical, functionally or visually. Almost all it does is optional, with a settings panel to tweak the user script.

I have also written various user styles for myself for particularly bad sites, over time, though I only have one such installed at present (on my phone, actually, to turn a poorly-implemented dark mode into a more complete and more actually-black dark mode). The progressive diminution has occurred mostly due to me ceasing to use bad sites.

I have more user styles on my browser, doing things like hiding the tab bar in favour of the Tree Style Tab extension, and the sidebar’s title.


Wouldn't the 'ReaderView' tools that present the article in a more comfortable / distraction free format count as user-applied stylesheet?


Probably not many, I use a bunch of my own styles all over the place to change things I don't like.


The last time I looked into it, user agents may support the '>>>' combinator for cases like user styling, where the user should trump the page content.


If web components will be built-in, I imagine it's possible for browsers to provide a way to style them in user-land.




Consider applying for YC's W25 batch! Applications are open till Nov 12.

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

Search: