I read the article and I am trying to understand it better. So do you mean that Web Components should be used just like normal HTML to code Component, together with frameworks such as VueJS or React?
So for example, some of the HTML in the "template:" section of a VueJS component would be tags which are defined by web components...
Not exactly. While they can be used in tandem, I'm not necessarily suggesting that they should be; rather, the two serve different purposes and solve different problems.
A framework component is effectively a reusable block of code. It's an organizational principle more than anything; modular and reusable, but not meaningful to the browser in its own right once rendered. A web component, on the other hand, is very literally a new HTML element, and is treated by the browser as such. Once defined, the browser itself sees that component as a meaningful entity in its own right.
While the difference between those two ideas is fairly subtle on the surface, there's a whole nest of smaller differences that result from it. For just one example, web components are perfectly AJAX-compatible with no extra strings attached - you simply add the HTML tag representing a component to the DOM, and it works out of the box, no matter when or from where you got it. Achieving that with a framework component requires some additional work at best, which may or may not have been done for you by the framework authors.
That's not to say one is necessarily better than the other either, to be clear - they're just different, and treating them as if they were the same does both a disservice.
> A framework component is effectively a reusable block of code.
I think that, for me as a newcomer to front-end development, this is the biggest takeaway: a framework component is a reusable block of javascript while a webcomponent is a reusable HTML element.
As a newcomer[1] it does not make sense to even learn the front-end frameworks. As an example, the time spent in learning the entire framework simply so I can 'watch' an element's value for changes, or propagate an element's changed value to other elements is going to be order of magnitudes greater than simply writing 3 custom elements that monitor and propagate values for any child element.
(PS. I like your post. I think a followup blog post with two concrete examples may make sense in refining your thesis:
Example 1. This is a popular React mechanism to do $FOO, here's how it is easier in a webcomponent.
Example 2. This is a complex webcomponent, here's how it is easier in React.)
[1] One who is not looking to put "react", "vue", etc on their CV.
For the reactivity stuff, you might want to read https://frontendmasters.com/blog/vanilla-javascript-reactivi... - it shows a bunch of no-library-required patterns that, while in a number of cases I'd much rather use a library myself, all seems at least -basically- reasonable to me and will probably be far more comprehensible to you than whatever I'd reach for, and frameworks are always much more pleasant to approach after you've already done a bunch of stuff by banging rocks together first.
> a framework component is a reusable block of javascript while a webcomponent is a reusable HTML element.
Web components/custom elements are reusable behaviours/functions - which can contain custom js, all bundled as a reusable HTML element.
Think of it a bit like an object in an object orientated programming language - the object has both data/state (DOM) and code/functions to manipulate that state.
> Both Web Components and Framework Components utilize JS and HTML.
If you're writing them, certainly.
For web designers, using Web Components means not having to know JS, not having to know React, not having to know hooks, not having to know usememo, etc.
That's, to my mind, a large enough distinction: the requisite knowlege to reuse a framwork's components needs a full time developer. The knowledge required to reuse a web component is ... HTML (and maybe CSS?)
> So do you mean that Web Components should be used just like normal HTML to code Component, together with frameworks such as VueJS or React?
I think if you are new to webcomponents[1] it might help if you list all the useful functionality you get from a front-end framework, and look up how to achieve the same thing using webcomponents (Custom element, templates, slots).
[1] As I am. I am, in fact, new to front-end in general.
On nice use, that took me maybe 30m to code up, is a `<remote-fragment>` element.
<remote-fragment src=/fragments/topbar.htmlf />
simply retrieves the specified file and adds it to the DOM where the `remote-fragment` is declared.
No need for server-side scripting to include common parts of the HTML page.
There's a bunch of similar use-cases currently satisfied by fat client frameworks or server-side languages that simply go away when you have custom elements.
So, yeah, you can do components with webcomponents they way you do much of react components, but there's some stuff that you can do with webcomponents that just makes life a little bit better[1].
[1] Experimenting with propagating state throughout a (client-side) application using only declarations in HTML, with custom elements performing stuff.
I like to think that I didn't reinvent it (just like react, et al didn't reinvent it), I only refined the concept into the simplest form that works :-)
After all, a custom element that takes a front-end newcomer 30m to write is absolutely preferable to a large infrastructure-based standard that, after 22 years, is still not included in the spec.
Look at the options for including HTML fragments in web pages:
1. Complex client-side react/vue/etc,
2. A server language ,
3. A build-step including a non-spec bundler/packer,
4. A `<remote-fragment src="..." />
My point is that webcomponents make quite a lot of complicated things redundant for particular use-cases. As time goes on I see the fat front-end frameworks having more of their functionality being replaced with less complex (to use) custom elements.
(Hence my experiments with value propagation using custom elements)
Tbf, you did specify 'server language' in a post further up the comment chain, but the the thing is that it doesn't have to be much more complicated that SSI -- assuming it's available for your deployment target, of course.
I've used those before, but I feel that having something that works within the spec, independent of any particular implementation's extensions is much more valuable for longevity.
Sure, you can use $A if using $B server, or use $C when using $D language, or use $E when using $F framework, or use $G when using $H reverse-proxy, or use $I when using $J CDN, or use $K when using $L hosted cloud service ...
Or you can just use what's in the specification which works on all of the above, but won't work on clients with Javascript disabled.
In this case you could use MutationObserver - although we are doing manually the logic web components provide, but my point is that you can do it also without using web components. My code doesn't include attribute changes, but this should be possible to also do with MutationObserver.
While you certainly could do this, a major benefit of web components is that you get all of this for free out of the box. It's less error/mistake prone, keeps your code cleaner and more obvious exactly what it does, etc.
Can you elaborate a bit more on the example in your footnote about propagating client-side state? Does that provide functionality similar to Alpine.js's data objects/stores?
Sure, but bear in mind it's only an experiment, so I do not expect this to be long-lived, or if it is, I do not expect it to look the same way as it does now, and even if either of the above remain true, I still think that alternatives such as htmx are preferably for multiple reasons, bar one (explained in the last paragraph of this post).
IOW, I expect this to be an experiment that I eventually throw away after having gained some insight. The `ps` in `psjs` below means "publish/subscribe".
The big draw for me about htmx is that common usage does not require knowledge of Javascript! This means that htmx (and my set of custom elements) does not require the creator of the front-end to know that npm even exists, much less how to use it. The same goes for Virtual DOMs, Hooks, tree-shaking/web-packing, promises and async, functions, and the whole container-ship full of arbitrary things that common front-end stacks need you to know.
My custom elements require javascript (for now), and require that the user know what is meant by 'publish a message onto a queue' and 'subscribe to a queue for messages of a particular subject'.
-------------------------------------
I have at least four custom elements: psjs-tree, psjs-bind, psjs-subscribe and psjs-publish.
I also have two JS functions, `publish` and `subscribe`: `publish` publishes an arbitrary payload (a JS object) to a channel (string) with a subject (also of string type). `subscribe` registers a callback function for a channel (string) with a pattern for the subject.
and then any code, anywhere else can do `publish(this, "ERROR", "Rpc Request", { errMsg: "Rxed 404"});`
My web components psjs-publish and psjs-subscribe execute those two functions (for publish, there is an `onevent` attribute). The psjs-publish component uses the closest psjs-tree ancestor to determine which fields go into the payload. The fields are set by psjs-bind. The psjs-subscribe does the opposite of psjs-publish, in that it uses the closest psjs-tree ancestor to determine which fields of the payload should be used to update the contents or values of the psjs-tree descendents.
For example, a form that can have the values reset by some other code (say, fetching them from a server) and can have the values submitted:
No need to apologize for the length of your post! It's interesting to read about your experiments.
Looking at your example with the psjs elements, it looks like the psjs-bind elements define what fields get captured and used in the published payload, as well as setting the input elements' values from a subscription event; is that correct? That does seem useful for keeping state synchronized across multiple local components.
It seems like you'd still need some JS if there's any client-side logic that needs to be run, though I'm not sure if there's a way to avoid that. I'm thinking of something like displaying different parts of the page based on multiple input fields. Maybe you could handle a lot of use cases like that with plain HTML and CSS, though.
> No need to apologize for the length of your post! It's interesting to read about your experiments.
Thanks. As a newcomer, I looked into what knowledge is required to produce a dynamic front-end, and completely 'noped' out of it after a few days[1]. The web component approach looks, to me, more future-proof as well as easier to use.
> Looking at your example with the psjs elements, it looks like the psjs-bind elements define what fields get captured and used in the published payload, as well as setting the input elements' values from a subscription event; is that correct?
Broadly correct, yes, but a little clarification - elements don't have to be input elements, then can be any elements. So, for example, if the psjs-bind 'for' target would is a span element, then the innerText content is updated. For input elements, the value is updated, etc. I'm still working out whether this is a good idea or not.
> It seems like you'd still need some JS if there's any client-side logic that needs to be run, though I'm not sure if there's a way to avoid that. I'm thinking of something like displaying different parts of the page based on multiple input fields.
You're correct; some JS is still needed! Of course I consider that a failure that needs to be rectified - for updating the page based on user actions (or input element changes) I'm considering a custom element that subscribes to a channel and listens for a subject pattern, and then changes its style fields (`display: none` to `display: block` (or vice versa)) based on the payload.
Keep an eye out for when I finally make this available to the world (maybe a name like 'ZeroJS', for example :-))
[1] Programming web services is dominated by out-of-standards/never-standardised technology - npm, build-steps (for front-end), frameworks, tree-shaking, commonjs includes, webpacking, etc. All I want is a quick way to produce dynamic web pages. A full 6-months of learning all the existing techis exactly my idea of a non-fun time.
> Broadly correct, yes, but a little clarification - elements don't have to be input elements, then can be any elements. So, for example, if the psjs-bind 'for' target would is a span element, then the innerText content is updated. For input elements, the value is updated, etc. I'm still working out whether this is a good idea or not.
Got it. I'm curious how this works out in practice; it feels like this would end up being a bit too unstructured in practice, but that's just a guess, and that might not be an issue when it's used in relatively small amounts.
> You're correct; some JS is still needed! Of course I consider that a failure that needs to be rectified - for updating the page based on user actions (or input element changes) I'm considering a custom element that subscribes to a channel and listens for a subject pattern, and then changes its style fields (`display: none` to `display: block` (or vice versa)) based on the payload.
I like the idea of being able to write most/all client-side logic with custom elements and/or a server-side rendering library. It can't cover all use cases without being so general that you might as well use JS, but there's probably some 80/20 point that covers most use cases with relatively simple tools.
It's not directly related to the article, but there's a question I've had for a while, related to this line:
> [Framework components] usually consist primarily of JavaScript, with only a very thin layer of HTML and CSS to provide their structure and are usually compiled away on the server side before they ever reach the DOM [...]
Is there any decent data on how many sites built with SPA frameworks end up using SSR, or even just anecdotal reports? A decent amount of what I read online seems to assume devs are using SSR, but I'm not sure if that's an accurate representation or just hype/pushing newer technology.
I actually recently contributed Shadow DOM support to the HTMX cobebase for 2.0! Once that drops, linking Facet and HTMX will only take a simple mixin.
41 comments
[ 3.0 ms ] story [ 82.1 ms ] threadSo for example, some of the HTML in the "template:" section of a VueJS component would be tags which are defined by web components...
A framework component is effectively a reusable block of code. It's an organizational principle more than anything; modular and reusable, but not meaningful to the browser in its own right once rendered. A web component, on the other hand, is very literally a new HTML element, and is treated by the browser as such. Once defined, the browser itself sees that component as a meaningful entity in its own right.
While the difference between those two ideas is fairly subtle on the surface, there's a whole nest of smaller differences that result from it. For just one example, web components are perfectly AJAX-compatible with no extra strings attached - you simply add the HTML tag representing a component to the DOM, and it works out of the box, no matter when or from where you got it. Achieving that with a framework component requires some additional work at best, which may or may not have been done for you by the framework authors.
That's not to say one is necessarily better than the other either, to be clear - they're just different, and treating them as if they were the same does both a disservice.
I think that, for me as a newcomer to front-end development, this is the biggest takeaway: a framework component is a reusable block of javascript while a webcomponent is a reusable HTML element.
As a newcomer[1] it does not make sense to even learn the front-end frameworks. As an example, the time spent in learning the entire framework simply so I can 'watch' an element's value for changes, or propagate an element's changed value to other elements is going to be order of magnitudes greater than simply writing 3 custom elements that monitor and propagate values for any child element.
(PS. I like your post. I think a followup blog post with two concrete examples may make sense in refining your thesis:
Example 1. This is a popular React mechanism to do $FOO, here's how it is easier in a webcomponent.
Example 2. This is a complex webcomponent, here's how it is easier in React.)
[1] One who is not looking to put "react", "vue", etc on their CV.
I feel like you're underestimating how easy this is to skrew up.
However, it's far far easier for a newcomer to screw up when approaching react or cue than when approaching a custom html element.
Time will tell as I use my experiment in more domains, more often and in larger apps.
For the reactivity stuff, you might want to read https://frontendmasters.com/blog/vanilla-javascript-reactivi... - it shows a bunch of no-library-required patterns that, while in a number of cases I'd much rather use a library myself, all seems at least -basically- reasonable to me and will probably be far more comprehensible to you than whatever I'd reach for, and frameworks are always much more pleasant to approach after you've already done a bunch of stuff by banging rocks together first.
Web components/custom elements are reusable behaviours/functions - which can contain custom js, all bundled as a reusable HTML element.
Think of it a bit like an object in an object orientated programming language - the object has both data/state (DOM) and code/functions to manipulate that state.
So is a web component…
To me there is a larg distinction but I do concede that to others there may be no difference.
If you're writing them, certainly.
For web designers, using Web Components means not having to know JS, not having to know React, not having to know hooks, not having to know usememo, etc.
That's, to my mind, a large enough distinction: the requisite knowlege to reuse a framwork's components needs a full time developer. The knowledge required to reuse a web component is ... HTML (and maybe CSS?)
I think if you are new to webcomponents[1] it might help if you list all the useful functionality you get from a front-end framework, and look up how to achieve the same thing using webcomponents (Custom element, templates, slots).
[1] As I am. I am, in fact, new to front-end in general.
On nice use, that took me maybe 30m to code up, is a `<remote-fragment>` element.
simply retrieves the specified file and adds it to the DOM where the `remote-fragment` is declared.No need for server-side scripting to include common parts of the HTML page.
There's a bunch of similar use-cases currently satisfied by fat client frameworks or server-side languages that simply go away when you have custom elements.
So, yeah, you can do components with webcomponents they way you do much of react components, but there's some stuff that you can do with webcomponents that just makes life a little bit better[1].
[1] Experimenting with propagating state throughout a (client-side) application using only declarations in HTML, with custom elements performing stuff.
After all, a custom element that takes a front-end newcomer 30m to write is absolutely preferable to a large infrastructure-based standard that, after 22 years, is still not included in the spec.
Look at the options for including HTML fragments in web pages:
1. Complex client-side react/vue/etc,
2. A server language ,
3. A build-step including a non-spec bundler/packer,
4. A `<remote-fragment src="..." />
My point is that webcomponents make quite a lot of complicated things redundant for particular use-cases. As time goes on I see the fat front-end frameworks having more of their functionality being replaced with less complex (to use) custom elements.
(Hence my experiments with value propagation using custom elements)
(SSI obviously does not require JavaScript.)
[0] https://httpd.apache.org/docs/current/howto/ssi.html
Sure, you can use $A if using $B server, or use $C when using $D language, or use $E when using $F framework, or use $G when using $H reverse-proxy, or use $I when using $J CDN, or use $K when using $L hosted cloud service ...
Or you can just use what's in the specification which works on all of the above, but won't work on clients with Javascript disabled.
It's a "choose your poison" scenario.
You could querySelectorAll and check the src attribute etc, then fetch the content put it in the innerHTML.
Or if you want to react to any such component inserted at times down the line or src attribute changes, you could use MutationObserver.For example it won't work recursively when a fetched fragment has fragments of its own.
Or when the js snippet loads before some fragment element is loaded (say, from a DOM update).
The nice thing about custom elements is that you get to treat them exactly like normal elements.
In websites, search engines ignoring the common elements that you would use this for, such as navbars, isn't a deal-breaker.
When I search Google for keyword FOO, results that have FOO only in the elements common to all web pages are useless results.
I'm typically looking for FOO in the content, not in the navigational elements or other common elements.
IOW, I expect this to be an experiment that I eventually throw away after having gained some insight. The `ps` in `psjs` below means "publish/subscribe".
The big draw for me about htmx is that common usage does not require knowledge of Javascript! This means that htmx (and my set of custom elements) does not require the creator of the front-end to know that npm even exists, much less how to use it. The same goes for Virtual DOMs, Hooks, tree-shaking/web-packing, promises and async, functions, and the whole container-ship full of arbitrary things that common front-end stacks need you to know.
My custom elements require javascript (for now), and require that the user know what is meant by 'publish a message onto a queue' and 'subscribe to a queue for messages of a particular subject'.
-------------------------------------
I have at least four custom elements: psjs-tree, psjs-bind, psjs-subscribe and psjs-publish.
I also have two JS functions, `publish` and `subscribe`: `publish` publishes an arbitrary payload (a JS object) to a channel (string) with a subject (also of string type). `subscribe` registers a callback function for a channel (string) with a pattern for the subject.
These are all global. A piece of code could do:
and then any code, anywhere else can do `publish(this, "ERROR", "Rpc Request", { errMsg: "Rxed 404"});`My web components psjs-publish and psjs-subscribe execute those two functions (for publish, there is an `onevent` attribute). The psjs-publish component uses the closest psjs-tree ancestor to determine which fields go into the payload. The fields are set by psjs-bind. The psjs-subscribe does the opposite of psjs-publish, in that it uses the closest psjs-tree ancestor to determine which fields of the payload should be used to update the contents or values of the psjs-tree descendents.
For example, a form that can have the values reset by some other code (say, fetching them from a server) and can have the values submitted:
Of course, this means that I have a line of js somewhere that looks like this: And another that looks like this:Looking at your example with the psjs elements, it looks like the psjs-bind elements define what fields get captured and used in the published payload, as well as setting the input elements' values from a subscription event; is that correct? That does seem useful for keeping state synchronized across multiple local components.
It seems like you'd still need some JS if there's any client-side logic that needs to be run, though I'm not sure if there's a way to avoid that. I'm thinking of something like displaying different parts of the page based on multiple input fields. Maybe you could handle a lot of use cases like that with plain HTML and CSS, though.
Thanks. As a newcomer, I looked into what knowledge is required to produce a dynamic front-end, and completely 'noped' out of it after a few days[1]. The web component approach looks, to me, more future-proof as well as easier to use.
> Looking at your example with the psjs elements, it looks like the psjs-bind elements define what fields get captured and used in the published payload, as well as setting the input elements' values from a subscription event; is that correct?
Broadly correct, yes, but a little clarification - elements don't have to be input elements, then can be any elements. So, for example, if the psjs-bind 'for' target would is a span element, then the innerText content is updated. For input elements, the value is updated, etc. I'm still working out whether this is a good idea or not.
> It seems like you'd still need some JS if there's any client-side logic that needs to be run, though I'm not sure if there's a way to avoid that. I'm thinking of something like displaying different parts of the page based on multiple input fields.
You're correct; some JS is still needed! Of course I consider that a failure that needs to be rectified - for updating the page based on user actions (or input element changes) I'm considering a custom element that subscribes to a channel and listens for a subject pattern, and then changes its style fields (`display: none` to `display: block` (or vice versa)) based on the payload.
Keep an eye out for when I finally make this available to the world (maybe a name like 'ZeroJS', for example :-))
[1] Programming web services is dominated by out-of-standards/never-standardised technology - npm, build-steps (for front-end), frameworks, tree-shaking, commonjs includes, webpacking, etc. All I want is a quick way to produce dynamic web pages. A full 6-months of learning all the existing techis exactly my idea of a non-fun time.
Got it. I'm curious how this works out in practice; it feels like this would end up being a bit too unstructured in practice, but that's just a guess, and that might not be an issue when it's used in relatively small amounts.
> You're correct; some JS is still needed! Of course I consider that a failure that needs to be rectified - for updating the page based on user actions (or input element changes) I'm considering a custom element that subscribes to a channel and listens for a subject pattern, and then changes its style fields (`display: none` to `display: block` (or vice versa)) based on the payload.
I like the idea of being able to write most/all client-side logic with custom elements and/or a server-side rendering library. It can't cover all use cases without being so general that you might as well use JS, but there's probably some 80/20 point that covers most use cases with relatively simple tools.
https://htmx.org/essays/right-click-view-source/
https://htmx.org/
> [Framework components] usually consist primarily of JavaScript, with only a very thin layer of HTML and CSS to provide their structure and are usually compiled away on the server side before they ever reach the DOM [...]
Is there any decent data on how many sites built with SPA frameworks end up using SSR, or even just anecdotal reports? A decent amount of what I read online seems to assume devs are using SSR, but I'm not sure if that's an accurate representation or just hype/pushing newer technology.
I loved her opinion, I've always shared that sentiment but I was afraid of saying it.
I also wish there was a way to develop such abstractions (WebComponents) with/in HTMX.
https://designsystem.digital.gov
Are you new or something?
Web components are so 2012