The Power of Web Components
hacks.mozilla.org
hacks.mozilla.org
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.
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 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.
Being able to do this client side with no code? Yeah, would be nice :)
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 :)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.
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.
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.
You can JSX (as first introduced by React) to pass objects to Web Components. See: https://github.com/wisercoder/uibuilder
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 your goal is very misguided. They all sucked, and were basically no better than MS Access forms.
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.
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).
Why do you say it was the wrong direction? Just curious. Is it because you ended up using React Native?
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.
This should give you a sense of the power of web components.
>>template.content.cloneNode(true)
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.
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>
`;
}
}You mean like Vue components? I think HTML components go on the same line, although this article does not emphasizes this.
https://www.styled-components.com/
Makes handling CSS in react a pleasure.
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....
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...)
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'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.
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.
<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.
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.
[1] https://src.chromium.org/viewvc/chrome?revision=234007&view=...
Edit: e.g for printing or to make reading / using easier.
It's probably worth noting that reader-mode -- another accessibility tech -- does seem to be fairly popular.
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.
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.
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.
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.
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.
Insteaed of a soup of deeply nested divs, there will be nicer and more meaningful structure of web components.
More complicated, but probably doable (with greasemonkey).