Why I don't use web components
dev.to
dev.to
[1] https://github.com/gildas-lormeau/SingleFile
[2] https://github.com/gildas-lormeau/SingleFile/blob/93d1e7c000...
I’m surprised there hasn’t been other nasty web stuff that required it.
I’m curious what google used to create that chromium bug report page (internal framework or a custom job). The internal tools targeting devs with good browsers will always have the most advanced stuff it seems.
Wasn't this the intention behind the older .mhtml format? I wonder what happened to that.
Also, do you have an option to choose to not save javascript?
The JavaScript injected by the extension will be included if and only if there are web components in the saved page. By default, all other scripts are removed.
If I want to introduce a design system, where all users of these technologies can work with a basic set of bread-and-butter buttons, input fields, etc., Web Components are the lingua franca of all of these technologies. That's why I use Web Components.
Now of course, not everyone is developing on monoliths globbed together with newer tech. But the reality is, most of the software used today is written this way. It isn't pure, functional, isolated modules / apps that startups going from scratch have the privilege of beginning with. Technology stacks slowly become the consequence of business acquisitions, etc. You can exert some control over things, but it will always be a moving target.
React + Redux + JSS just really matches how I've always conceptualized about building web based applications. I absolutely favor material-ui as a component library. I've been building web applications for almost two and a half decades. React is the first framework that felt "right" to me, and still did after using it. I've used a LOT of options over the years.
I do think WC can be used with React in some cases, and that it's probably a better approach if you're building mostly static content and wanting to add additional interactive features outside of core display.
I also think in 5+ years there will be a couple library options that makes using WC a better option for application style development.
It will change some things for sure. But we’ve had compile-to-js languages for some time and they’re a pain. Compile-to-ws is better, but still has the same fundamental pain points (debugging mostly, and then browser compatibility).
By changes everything, you mean no large amount of devs will keep targeting vanilla html+Js and I just can’t imagine that future.
But I still find the debugging very weird. The fact that the VM is stopped on a different line of code than I’m looking at seems to always introduce small little confusions. Have you never had that experience?
It’s possible I’m just overdue to try the tools again. I’ve had a lot of bad experiences.
And all of that said, I happen to like JS. It's my favorite language. While I'm really green with it, I'd consider Rust my second fav. C# third. In the end, I find that I can be incredibly productive with JS + NPM and that cannot be understated. I'm able to leverage community repos that cover everything under the sun and write less than half the code and better cover my use cases for good enough performance. When I need more, I'll leverage other languages/tools, most of the time, I don't. And even when I do, I tend to lean on Node/JS for orchestration.
The list of languages is bigger that I would've thought: https://github.com/appcypher/awesome-wasm-langs
In terms of enterprise usage, I'm not seeing any mature polyfill implementations out there, but I did find https://github.com/lukewagner/polyfill-prototype-1.
1. Good point, though someone is going to write a server side renderer to pre-generate the custom tags into regular html tags.
2. A web component can import its own CSS file, no need to put styles in JS code or string.
<style>
@import "/css/shared-styles.css"
@import "/components/my-widget/my-widget.css"
</style>
5. Composing with sub-components works just fine with or without slotted content. What's wanted in item 5 was a special case for dynamically including content at runtime. That's best left to Javascript when triggered with property setting.6. For properties and attributes, it's simplest to just reflect all property get/set calls to attributes, using attribute as the only storage. I have some helper function to do that.
attrAsProp(comp, attr, property)
Object.defineProperty(comp, property, {
get: function() { return comp.getAttribute(attr) },
set: function(v) { comp.setAttribute(attr, v) }
});
9. Global namespace is a problem but it also makes things simple to use. We don't want complicate stuff like xmlns.Here's my issue with a browser monoculture. With 3 or 4 major browsers, it was easy to tell what features would survive. The specs were never great at that -- there were some early spec'd features that never got widely implemented. But any feature that could convince people at Google + Microsoft + Apple + Mozilla to all implement it would be around for a long time.
With Microsoft switching to a Chrome-based engine, this is a valuable data point we've lost. Essentially, instead of new features being opt-in by default, they're opt-out. We've seen it before: when one browser has a majority market share, nobody else can afford to tell them an idea is bad.
- https://www.neowin.net/news/w3c-and-whatwg-agree-on-single-h...
1. Browser A adds new non-standard feature.
2. Users like it enough to start using it widely in their apps.
3. Other browsers are now motivated to implement the feature so that those apps work in their browser too.
4. Because of that, there is now incentive to standardize. Finally, the feature becomes a standard.
The sketchy part is that step 2 only works when users deliberately choose to build apps that only work in a single browser. That idea anathema to standards folks, but as far as I can tell, the consensus process does rely on it most of the time. That's how we got JavaScript, XHR, <canvas>, etc.
It's very hard to convince several independent implementation teams that a feature is a good idea if no one is using it yet.
So long as Google follows the ideals of Open Source Governance on the project and listens to PR feedback, Microsoft might not be wrong about that.
That said, Google also has a history of taking their ball and going home when they aren't getting what they want from Open Source Governance (the increasing divorce between AOSP and Google Play Services for example, or closer to this particular debate the fallout with Apple that caused the Blink fork from WebKit). I'm almost tempted to bring popcorn to the Chromium mailing lists in anticipation of whatever drama is about to happen.
For a broader meaning of Web Component (plain React, Vue, etc), they provide good encapsulation and some degree of local reasoning. But harder to communicate and stay sync with other components/server.
For Web Component with a centralized store approach (Redux, Mobx Vuex, etc), it breaks local reasoning, and it requires the user to manage the life cycle of data instead of just reuse the life cycle of components.
So there is still quite some space to improve. I found the idea of GraphQL co-location is pretty interesting. And I also found there's a ClojureScript library named Fulcro[0] specifically trying to provide the ability to have a global data store while keeping the ability to local reasoning.
They are not a direct analog to modern frameworks, and it's completely expected that developers will use helper libraries to get better DX like declarative and reactive components.
I work on two such libraries: lit-html and LitELement. Combined they give you just as much declarative and reactive power as frameworks, much better DOM and style isolation, better performance, and smaller size than just about anything else out there.
Compare a styled Hello World example to React or any other framework:
import {LitElement, html, css, property, customElement} from 'lit-element';
@customElement('hello-world')
class HelloElement extends LitElement {
static styles = css`
:host {
display: block;
}
p {
background: pink;
}
`;
@property() name;
render() {
return html`<p>Hello ${this.name}!</p>`;
}
}
(this example uses decorators because I think it's clearer, but we support plain JS as well)Compared with svelte from the article:
<script>
export let name;
</script>
<style>
p {
background: pink;
}
</style>
<p>Hello {name}!</p>
# Size comparison## lit-element
lit-element.js?module: 8421 bytes
lit-hello.js: 340 bytes
## svelte
bundle.js: 2628 bytes
bundle.css: 72 bytes
2) Svelte bundles the runtime operations that each component uses directly into every component. HelloWorld doesn't use much, so it'll be small, but most component are not HelloWorld and most applications will not have only a single component. The cost of the common dependency on LitElement is amortized over all the elements that use it.
Why gzipped? Bytes of source is a fairer comparison. Parsed source code should be the comparison, not transfer time.
> HelloWorld doesn't use much, so it'll be small, but most component are not HelloWorld and most applications will not have only a single component.
Then why dare other to compare sizes of a Hello world example? :-)
Regarding the comparison in source bytes, here it is:
minified lit-(element + html)[1]: 21.4k
I'm not sure it "amortizes" svelte when having more components, when runtime in hello world example is less then 8x size. Would love to see an example. Tried finding lit-element in "Real World Example" [2], but did not find it. Maybe you have some pointers?
1: https://bundlephobia.com/result?p=lit-element@2.2.0
2: https://www.freecodecamp.org/news/a-realworld-comparison-of-...
CSS Modules will make it possible to directly import a Stylesheet: https://github.com/w3c/webcomponents/issues/759
In a good model of the web, html is your data, css is your styling, and javascript doesn't really exist.
In another model of the web, your data would be your data, html/css would work together to form a scene-graph. Javascript defines the relationship between your data and it's scene graph.
That friction, are we using html as data or as part of our scene-graph, is what causes a lot of these problems.
I like web components because they bring you closer to having html be just your data. I like react because it brings your html closer to being just your scene graph. Both solve the same underlying problem from different directions.
Not XSL:FO?
I still kind of feel like I need to sit down and figure out exactly what my issue is with the current spec, but roughly speaking I guess I'd say that the DOM should be a standardized display layer, not a way to store internal application state. Or put it another way, the DOM is for your users, not for your application. I don't think that fully captures the problem, but it's a bit closer.
Regardless, I often flail when people ask me why I'm a little skeptical about the way web components are currently designed, so at least now I have something to point them towards.
Good design seeks to limit the amount that we rely on that state in the DOM. Typically speaking, I try to listen for events on input elements. I don't rely on them as a state store.
Text inputs in particular here are kind of a good example, because they often get used in combination with validation and autofill. I've seen a lot of bugs and spaghetti code come out of running validation on field update, and using that validation to update or fill in other fields, and needing to track which update will trigger another event, and so on.
I'm not saying we should get rid of interactive elements on the web, but I think they fall into something of a grey area that shouldn't necessarily be encouraged. I use inputs to get the current user state, and to respond to user input -- I try very hard not to use them as a state store for application-level data.
I kind of think I would still say the same thing about inputs as I would about regular HTML elements -- input elements are for your users, they're not for you. They're not your interface, they're just the way your users communicate with you.
If we are lucky, most of them die in a space of 5 years, and then you get to enjoy project contracts to port all those shiny apps to boring sound, long lasting technology stacks.
I think most good ideas in software engineering have already been discovered, and primary innovation has long been applying existing ideas more effectively. Hard to argue Angular.js or React does anything that has genuinely never been done before, and same to ColdFusion.
Absolutely wrong, Javascript was always fast enough to make web applications that had the responsiveness of desktop apps. The problem is that nobody was writing desktop apps in the browser; they were writing server-generated web pages that offered the users some extra interactivity via js. So they had to look for elements in a static template, and hook into them or perform transformations on the fly, instead of generating everything programmatically as it's done now.
IE6 and 7 were so slow in both JavaScript execution and DOM that it’s silly anyone would ever claim JS execution was “fast enough.”
The art of fast JavaScript was once arcane, but its clear we’re so far into fast JS execution that nobody even remembers how awful it was. Especially when you had to support IE.
Oh, and let’s not forget the incredible increases in CPU speed. Even a later Core 2 Duo machine I have is awful for browsing the web, basically unusable without uBlock Origin.
I mean sure. Even pre-XHR you could write apps that were effectively SPAs, but manually manipulating HTML elements in your business logic isn’t exactly what I’d consider “modern.” Desktop apps at the time, even ones written on Win32, tended to put a couple layers of abstraction around the underlying resources, to say nothing of Qt and its entire programming model worth of abstractions. YUI, mentioned above, was already a significant step up from that.
But those toys were nothing compared to what you can do today. Today you can literally compile the entire Qt libraries and a whole Qt app to JS and run it on Canvas and it’s usable on a fucking phone. Part of that is w3c typed arrays (and WASM, for extra perf,) but most of it is just years of raw optimization and CPU speed improvement.
In 2009, I was still struggling to draw 60 frames per second (important to note: consistently. It was actually hard, at higher resolutions.) on canvas 2d. Just a few years later Unreal and Mozilla demoed Unreal Engine running at 60 fps in pure JS and WebGL.
No reason to diminish what I’m sure you did accomplish in 2005 - it was probably amazing for 2005 - but I absolutely disagree that we didn’t experience life-changing performance improvements. The performance improvements we got enabled huge React and Angular apps to be possible. If you don’t believe me... again, try browsing the modern web on old machines. I've just recently set up a machine with an 800Mhz PowerPC from ~2004. Even with fairly modern Firefox, and adblocking, modern sites are basically unusable.
Addendum: today’s bundle sizes also would not have worked too great on older internet. Another performance characteristic that is largely taken for granted today: parsing and network speed!
Of course I don't disagree with this either. But this (as well as trying to run modern internet websites on older hardware) doesn't mean much- it's a fact that software always fills up all the capacity allowed by hardware, sometimes with features, but more often with frills and more layers of indirection. What I disagree with is that javascript (and browsers) were too slow to make interactive web applications: in fact they were possible, and the ones we still use were born around 2005: gmail (probably faster then than now), google spreadsheets, maps (I made a complex dashboard in 2005 incorporating microsoft maps, that became bing) etc.
Programming was much more "close to the metal"- as much as this means anything in a web browser- but the results were usable- not as graphically fancy or feature rich as today's, but ok for many use cases.
Bundle sizes also have exploded as a result of the complexity of the frameworks. But that doesn't mean the applications are more interactive or have more features, they're just fancier and, from the point of view of developers, more maintainable.
Still, I don’t think YUI necessarily had the mindshare the same way Angular or jQuery once did...
It was pretty much a proprietary PHP before PHP was somewhat rehabilitated, except it somehow made less sense.
Most modern front-end frameworks aren't just custom tag languages; their strength is in component lifecycles. ColdFusion never really had good support for events at the custom tag level.
But I can use Vue's component which don't care about the standard and just compile everything down to a plain JS, so it works well with any browser.
On the other hand, PolymerJS tries too much to utilize the web component standard. I didn't originally thought that this would be a bad thing.
Svelte does look good. I checked it out a year back and thought that Vue should've moved more stuff into its compiler if it could.
Lit, Skate, Stencil, etc, solve those limitations, but if you are already using a complicated toolchain and third party code for doing the heavy lifting I don't see much value in WCs.
Also:
> Unlike React.js UIBuilder does not do incremental screen updates.
Which means you now have to start worrying about which parts you have to update. So again, you probably need something like MobX.
It’s not that any given library couldn’t make its own. It’s that having a single implementation “canonized” in the stdlib means that every library that wants this functionality will be using the stdlib’s implementation, and stdlib functions will also be able to consume or produce that type when it makes sense, and so you’ll have an ecosystem that all interoperates by passing around and transforming this shared type.
Also, standardizing Web Components also means changing the semantics of DOM parsing for user-agents other than browsers. My random Python HTML crawler lib isn’t going to parse some third-party library’s implementation of Web Components; but it is going to parse standardized HTML Web Components.
Your random Python HTML crawler is welcome to try and parse standardized HTML Web Components, but since every single one is going to be named differently and have separate controls and interfaces for accessing data, your crawler isn't going to get very far.
I am moderately concerned that Web Components are a step backwards for the semantic web, not a step forwards. Particularly after seeing other comments on this post that the shadow DOM is only accessible through Javascript in some situations. To me, web components feel over-engineered. I'm not sure exactly what it is, but I can't help but feel like there's a simpler answer to this problem that would have worked better for everyone.
Maybe a better, Javascript free implementation of HTML imports? The last spec got rejected for very good reason, but it's not like the core idea was necessarily bad. Then maybe throw out Shadow DOM entirely and replace it with some kind of more flexible/accessible scope system instead?
Is it about avoiding namespacing your CSS? Is it about shipping reusable components for many sites, hosted on some other domains? Loading JS on demand? What?
It just seems overly complex and limited with its slots etc.
I want to have Shadow DOM that encapsulates trust, so the enclosing parent javascript cannot access its contents!!
1. Progressive enhancement - but I think that websites should work without JavaScript wherever possible
At a certain point, backwards compatibility becomes more a of hindrance than a help, in an effort to support an ever shrinking demographic. Now I will give the author the fact that they used the word website, where my frame of reference is building modern web applications, falling back to no-javascript to me would be going back to server rendering and the dumpster-fire of page-post AS/JS/PH/P's.
2. CSS in, err... JS
Separation of technology, is not separation of concerns. This has been argued over JSX and it has been shown to be a huge productivity improvement. If everything for a component is internal to that component and does not need to be reused in a way other than using that component then there is no reason to separate the technology. As both of their concerns are the UI component. In that regard, where everything is encapsulated to the component (HTML, CSS, JS) it is actually a better pattern to not separate technologies as it makes the component easier to reason about.
You define your page with an XML document of UI components and javascript exists for animation and data fetching.
I could be wrong but that's just what it seems like to me.
You define your page with custom html tags that won't even render properly without Javascript. And then you need Javascript for literally everything: initialising the component, data fetching, inserting data into the DOM, updating data in the DOM etc.
I'm SURE web components allow a non-js fallback, or that should be introduced into the spec.
See here for progressive enhancement of web components https://googlechromelabs.github.io/howto-components/howto-ta...
Dont' SPA's require defining multiple components? A non-js component inside of the html page and a JSX component or whatever inside of the SPA.
In vast majority of cases it's nowhere near "basically web components".
> I'm SURE web components allow a non-js fallback, or that should be introduced into the spec.
They don't. All they can do is render static content inside if they have any.
> See here for progressive enhancement of web components
I fail to see where you see progressive enhancement. It's literally dozens of lines of Javascript code. If you disable JS on that page, you'll get just the static content with no functionality.
> Dont' SPA's require defining multiple components? A non-js component inside of the html page and a JSX component or whatever inside of the SPA
All you do is attach the root node of an SPA to any element in the DOM. A common approach would be:
<body>
<div id="app"></div>
</body>
// elsewhere in JS code
X.render(document.getElementById('app'), rootNode)
where X is your framework of choice.What would a non-JS fallback look like that isn't this? Where would the functionality come from if not JS?
That's not "graceful degradation". It's full loss of functionality. Whereas graceful degradation is
Graceful degradation is the ability of a computer, machine, electronic system or network
to maintain limited functionality even when a large portion of it has been destroyed
or rendered inoperative.
However, I was primarily responding to "javascript exists for animation and data fetching". As you clearly see, it exists for way more than just that.This is outright false
"If JavaScript does not run, the element will not match :defined. In that case this style adds spacing between tabs and previous panel."
https://googlechromelabs.github.io/howto-components/howto-ta...
The styles still run....
When JS is disabled you are left with a bunch of arbitrary tags in a structure that doesn't match the structure they have when JS is enabled.
That said, I don't think there's a good answer to this problem. Components-as-macros would run without JS, but then you have the LISP problem with composing macros (maybe this is a solved problem, but I haven't read Common Lisp's spec or used Racket in anger).
What else does it do besides render JSX components and manage their state just like a web component except with more indirection?
> All you do is attach the root node of an SPA to any element in the DOM.
You missed the point of what I was saying
The root node is a single node...where do you define the rest of your components? IN JAVASCRIPT. IF you want progressive enhancement you have to define a SECOND SET OF NODES IN HTML. THIS IS REDUNDANT.
>I fail to see where you see progressive enhancement.
Why don't you actually read the thing? "If JavaScript is disabled, all panels are shown interleaved with the respective tabs. The tabs now function as headings."
1. There many more ways to implement SPA than JSX.
2. WebComponents have exactly zero state management capabilities, and you need to implement your own ways to deal with state
So, SPA frameworks provide the following:
- state management
- optimised/batched updates (they can flush to the DOM efficiently thus avoiding jank, unnecessary re-paints and reflows)
- async rendering
- easy fallback states for async data fetching
- data fetching
- data propagation (for example, from parent to a deeply nested child)
- data binding
- render targets other than HTML (example, canvas, webgl, native mobile apps)
I'm definitely missing more. None of the above are provided by web components, and you will need to bring your own frameworks/libs to cover all those points.
Also, this SPA cargo cult has been around a lot longer than Web Components which have just the past year or two become cross browser compatible.
I expect great things from them.
Web Components and their associated libraries can and will do all of those as they grow.
What do you think SPAs are? They are just Javascript. You add all that Javascript on top of web components and you ... end up with an SPA
> Some are benefits, however, two way data flow is a janky model in itself that could possbily be done away with by a nice data structure imo.
Quite a few frameworks don't have two-way data binding. React famously doesn't.
> I expect great things from them. Web Components and their associated libraries can and will do all of those as they grow.
So, they can't do those things and you're asking "what are SPA libs good for"?
You clearly have little to no experience with web development.
In a parallel universe where web components came first the built-in tags would themselves be web components backed by JS instead of having native implementations.
Native Web Components are a core spec in the BROWSER.
A web component can be completely styled and created without Javascript.
html5 encourages custom tags, and can be styled with plain CSS?
The fundamental difference here is that HTML needs to know what class to instantiate when it sees a tag. Supplying that unlocks a lot of power, like custom elements in the main document, Markdown support for free, easy integration with existing CMSes.
We can and will solve the single namespace problem though.
By the way I just noticed you're the maintainer of lit-html. How does it compare to HTM[1]? They both look like they accomplish the same goal but HTM's implementation looks smaller.
But htm is just a shell over VDOM (that's why it's small, you still need the real VDOM implementation).
React + htm still suffers from its use of VDOM and the diff that necessitates. lit-html doesn't do a diff because it remembers where the dynamic expressions are located in the DOM, so it can directly update them.
[Edit] Oooh, I see where I got mixed up: in your README, the only part where I can find mention of this feature is in the very last part of this line:
> "lit-html templates are plain JavaScript and combine the familiarity of writing HTML with the power of JavaScript. lit-html takes care of efficiently rendering templates to DOM, including efficiently updating the DOM with new values."
Specifically the "including efficiently updating the DOM with new values" part, that's the only mention on this page, and it's literally right after where I started to skim due to (incorrectly) assuming the rest of the sentence was just a continuation of the first part.
That feature should probably be mentioned more prominently.
Also, if it has the ability to re-render based on state updates (e.g. from onclick callbacks), an example would be really important to know how to make use of that feature.
On the other hand, these frameworks can be completely unnecessary overhead for one or two person teams. I'm currently using Preact for personal work, just because of how simple and lightweight it is.
To the author's point on site's that work in older browsers or without JS, unless you're building a product for government use or for an org that has really archaic IT requirements, the chances of needing polyfills that aren't provided by default in the framework are really low. The chances of someone needing your site to work without JS is also really low, especially if you're providing any sort of complex functionality.
I'm curious about this. A graph of say, what percentage of the top 500 websites can't run without JS, over time, would be interesting.
My assumption is that it's a non-trivial percentage, and growing.
The biggest issue I've seen with virtual-DOM sites is SEO. Google's crawler started using JS a number of years ago, but there are others that don't.
Does your site work without JS? If not, what justifies the more complex development and the degraded user experience for you and your audience?
For sites that just convey text, they should work without JS. This would mostly solve accessibility (a11y) issues if sites looked to use simplicity wherever possible instead of adding complexity to solve issues caused by complexity.
You can sort of imagine it as another generic "web component" framework, but blessed into full, native browser support, and getting some features/technologies that required browsers to implement new features to support them.
And if we had those element types mobile web would be easier to use.
So Chrome and Firefox please invest in new HTML elements for mobile touch web..
Just use Elm-lang.
In all seriousness, what is the business-value argument against using Elm?
Edit: grammar, speeeling
My response was, why would you hire a Java programmer who is unwilling or unable to learn Python?
In this case, I would hire a normal person who was good at Sudoku and teach them Elm before I would hire, say, a React specialist who refused to pick up Elm.
No escape hatches: The only one who is allowed to do bindings to Javascript is the maintainer.
No typeclass mechanism or similar.
> Terrible backwards compatibility.
At version 0.19...
> No escape hatches: The only one who is allowed to do bindings to Javascript is the maintainer.
I trust Evan Czaplicki. Did you read his thesis[1]? M'boy can think.
> No typeclass mechanism or similar.
Okay, but then my question becomes what business value are you unable to realize without a typeclass mechanism?
In other words, what is the vital use-case or feature that is so much easier to implement with a typeclass (relative to some other, less elegant solution) and that is so valuable that it counter-balances or outweighs all the benefits of using Elm?
(Same question applies to JS escape hatches. And, in theory, if the payoff was high enough you could fork Elm and patch it to do what you needed.)
[1] "Elm: Concurrent FRP for Functional GUIs" https://www.seas.harvard.edu/sites/default/files/files/archi...