
Implementing single-file web components - k0n0pka
https://ckeditor.com/blog/implementing-single-file-web-components/
======
spankalee
I've been on the Polymer team, making web component libraries, for a long
time. And while we used to promote "single file" style authoring in HTML
files, we've come around (me very strongly) to the idea that it's better to do
single-file components in _JavaScript_.

This has resulted in our newer lit-html and LitElement libraries, where the
DOM rendering is done in JavaScript, but it's still possible to do single-file
style:

    
    
        import {LitElement, css, html} from 'lit-element';
    
        export class MyElement {
          static styles = `
            :host {
              display: block;
              background: red;
            }
          `;
    
          static properties = {
            name: {},
          };
    
          render() {
            return html`
              <h1>Hello ${this.name}</h1>
            `;
          }
        }
        customElements.define('my-element', MyElement);
    

There are a number of reasons why this is better, IMO. Not requiring any
builds and utilizing the JS module graph are big ones.

The most important though is that the essential job of templates is to
interpolate data into DOM. It's much easier this by building DOM in JS, than
by trying to access and transform data in HTML.

Templates need some kind of expression language. If the template is in HTML
then you need to invent expression delimiters, the expression syntax and
semantics, and a way to get data into HTML: HTML doesn't natively have a way
to refer to JavaScript objects. This is all custom, needs code to implement,
and you need to train developers on it.

On the other hand if you write templates in JS you can take advantage of full
JavaScript expressions, imports, and natural lexical scoping... and the data
is typically already in JavaScript.

~~~
redindian75
> On the other hand if you write templates in JS

As a non-programmer (UX), I used to watch Polymer with so much interest, since
it had HTML tag-like syntax. I copy paste component codes & construct an UI.
There was simplicity in <googlemaps lat="89.2" long="123.2"
draggable="false"></googlemaps>

Now with lit-html, it went from unique HTML/WebComponent for non-coders, to
another one of the JS frameworks out there.

~~~
spankalee
I'm only talking about the _implemention_ of web components. You can still use
any custom element from HTML.

If <google-maps> was rewritten in LitElement, you'd still be able to write:

    
    
        <google-maps lat="89.2" long="123.2" draggable="false"></google-maps>

------
seph-reed
The unfortunate issue with components is that they're kind of like wysiwygs or
bootstraps. They save a small amount of trouble in the beginning, but always
bite you in the end.

That being said, if it's all in a single file, you can copy and paste that
file into your project and then modify the thing, unless the single file is
itself a bundle.

At my last company we tried to make a button component. But then we wanted to
be able to change url with it. But then if you ctrl-click, it should open in a
new tab. And then there were certain styles of button, with mixed and matched
shapes.

Nowadays, I see components as single use, or specific to a project. And for
anything that's more about a visual than a function (ie buttons), just use css
classes and implement the underlying Elements from scratch.

Point being, everyone wishes they could model the perfect abstraction of a
component, but then you start adding config to make it do everything until
it's basically its own miniature programming language (with worse docs).

~~~
potta_coffee
I've encountered this issue a lot. Really, a button is a very fine-grained bit
of functionality to write a component for, in my opinion. A component is just
the wrong level of abstraction for a button. For me, it's worked to make a
component when I have a grouping of elements that I will re-use together. For
instance, I wouldn't make a component for a form field, but I would make a
component for an entire form, if I would use that form again.

------
TekMol
It is insane that HTML has no "include". None of all this would be needed if
we could just do:

<include src="myComponent.html>

~~~
woodrowbarlow
it was proposed and implemented, then the standards body did an about-face.

[https://hacks.mozilla.org/2015/06/the-state-of-web-
component...](https://hacks.mozilla.org/2015/06/the-state-of-web-components/)
(ctrl+f "HTML Imports")

"HTML Imports do lend themselves well to a simpler/more declarative workflow.
[...] Imports don’t offer enough control to be taken seriously as a dependency
management solution. [...] Mozilla had a working implementation behind a flag,
but struggled through an incomplete specification."

which to me reads a bit like: "js frameworks won't use it, and the spec didn't
get enough love because everybody's only thinking about frameworks rather than
vanilla-js."

~~~
chrisfinazzo
Sigh.

A web that was built on documents fragments because the JS and server-side
developers _think_ writing raw HTML and CSS is gross.

Email developers would like a word with them.

This isn't going away, and at some point, adding more abstractions is actually
harmful.

As I have little else to do at this point - Tl;dr When you work for a public
library, but are closed the public, nothing happens - I'm rewriting a small
microsite I made for job hunting purposes.

Other than a Service Worker cache, it's markup and styles all the way down,
stitched together with Make.

For my blog, I've stuck with Liquid, because Jekyll - _which I actually like_
(ducks) - will be interesting to see if this gets revived and actually lands
one day.

~~~
woodrowbarlow
would you mind sharing the source or stack for your microsite? your setup
sounds like something i'd enjoy using.

~~~
chrisfinazzo
Code is here - [https://github.com/chrisfinazzo/reverse-job-
posting](https://github.com/chrisfinazzo/reverse-job-posting)

Started on GH Pages, but moved to Netlify which gives me a bit more fine
grained control.

Pardon the dust;

First, I'm not a graphic designer and second this is actually an older deploy
that I've "locked" so I can continue tinkering with the master branch behind
the scenes. Will be a single page with just anchors to navigate when done.

Everything old is new again. Homepages, kids, ask your parents about them :)

------
woodrowbarlow
question for HN: do single-file components _actually_ work better for you than
having the script, markup, and styling in three separate files?

i've been doing a little Vue and a little WPF/XAML lately. with Vue SFCs, i
find myself constantly scrolling up and back down in long files. with WPF, i'm
switching between the XAML markup in one editor tab and the code-behind in
another. i find the WPF workflow is better for me, because i lose my place
less often.

~~~
burlesona
Yes, and for a very mundane reason. When an application is long-lived there’s
inevitably some bit rot where one layer (template, style, or JavaScript) gets
removed for some reason, and one or more of the corresponding layers is
accidentally left in the code. This is especially likely to be CSS.

With single file components it’s much easier to track the dependencies and
rebuild / scrap chunks of code without leaving cruft around accidentally.

~~~
hombre_fatal
In over 10 years I've never worked somewhere where anyone was trying to prune
unused CSS, especially in the traditional approach where you just have large
.css files that become append-only.

Not until I experienced component-level CSS did I see it happen since now it's
relatively trivial to see unused CSS.

------
rwdim
upvoted: it’s repost of a repost of a 2 year old article, but still great
article. original from 2018 :[https://medium.com/content-
uneditable/implementing-single-fi...](https://medium.com/content-
uneditable/implementing-single-file-web-components-22adeaa0cd17)

~~~
mrrobotchicken
The original article is actually this one as it was written by us and
initially posted to our Medium account only to realize last week that we
somehow forgot to publish it on our blog. Whoops.

So - this here is an updated, revised and improved version. Enjoy!

~~~
tadzik_
Thank you for posting this on a less hostile platform :)

------
spacedcowboy
Cappuccino does this. Compare the speeds of the work-in-progress
([https://wip.laser-tags.net](https://wip.laser-tags.net)) and the same site
([https://laser-tags.net](https://laser-tags.net)) after doing a ‘jake
release’ which pulls the 90 or so files into a single .sj one.

There’s also ‘jake press’, which goes through the JavaScript code, pulling out
anything not actually referenced and binning it

(edit: and it occurred to me while in the shower, if anyone wanted to tell me
where (roughly) you are located, and loading time for the 'released' site,
it'd make me happy :)

------
petilon
Here's an example of single-file Web Component. Markup (JSX syntax with
embedded JS expressions), CSS and JS are in one file:

[https://github.com/wisercoder/uibuilder/blob/master/WebCompo...](https://github.com/wisercoder/uibuilder/blob/master/WebComponentsDemo/elements/ZxListEditor.tsx)

All you need is this tiny 250-line lib:
[https://github.com/wisercoder/uibuilder](https://github.com/wisercoder/uibuilder)

------
floatboth
Polymer used to do the HTML Imports thing. Now LitElement does everything in
JS files and it's.. better? Works great with bundlers like rollup, fits the
npm module resolution thing much better.

------
awinter-py
'can your tool run a full-featured app from a single file' is a really
important test of simplicity

esp given how people learn online, a single-file example is much more
palatable on e.g. stack overflow vs three files

way friendlier to learners

not that anyone is building large production apps with single files, but
tooling quality matters and this is one way to measure it

------
TheRealPomax
Why are the on-page examples images, instead of web components?

------
eximius
Flip the order of the sections and it's how I write Svelte components.

------
briandilley
Angular

