hyperHTML seems very similar, could a FAQ explain the difference?
They are indeed very similar, and hyperHTML is amazing work. At some point it might make sense to get into detailed comparisons, but for now I'd just say that we're very happy with this implementation strategy, in terms of speed, size and simplicity.
In particular, the public API for adding features matters a lot to us, which you can see in practice with the repeat and until directives, and the ability to set properties and declarative event handlers in lib/lit-extended.js. I've also been trying to be careful to have as few limitations around what kind of values can be placed where in templates.
Also, we're keeping in mind potential standardization of the two main phases in lit-html: HTML-in-JS parsing of templates (Similar to E4H) and what's been called "template parts" (the ability to set the content of "holes" in cloned template instances). We would like to keep it conceivable that lit-html is eventually obsoleted by the platform itself.
Right now we're still focused on the ergonomics and performance of lit-html itself. Comparisons are tricky business, and can come a bit later if needed.
hyperHTML seems very similar
to be honest, this looks like a half baked clone of hyperHTML and I'm surprised there was no mention whatsoever to such library, or its author, that I think "inspired" 90% of this project ... anyway ...
_viperHTML_ is a NodeJS backend version of _hyperHTML_, I think it's hard to standardize the pattern in a way that's useful for both worlds, so I'm curious to know more about the following:
Also, we're keeping in mind potential standardization of the two main phases in lit-html: HTML-in-JS parsing of templates (Similar to E4H) and what's been called "template parts" (the ability to set the content of "holes" in cloned template instances).
With @marcoscaceres we were also thinking about possible standardization so it'd be great if someone would talk to us, since we've used this pattern for the last 6 months already.
It's clear this project is still a work in progress but if somebody would like to know differences as of today with _hyperHTML_ only, 'cause it cannot be compared with _viperHTML_ at this point, these are the main things I've figured out going through the code:
html<td>nope</td> on browsers that don't support template and you'll see empty holes in tablestextContent can be used, you need third parts extension to create basic lists or you need a render function per each single template. This can be a limit, it was a limit for me when using _highlightjs_ for code examplessetAttribute which might not produce the desired behavior if the attribute is inherited and/or boolean. You cannot <button disabled="${isDisabled}"> as example, so it's half useful with forms and other cases with special attributes<span attr="a ${"b"} ${'c'} ${"d"}"></span> ... imo, a bit eyes-hurtingonclick too. With _hyperHTML_ events are always DOM Level 3 with auto removal when changed or nullified and no conflict with DOM Level 0. You own the template, you own the events.About extensions
Usage of extensions here is a very nice idea but it also means developers need to learn something else beside the rules to create valid templates and the signature to render them.
One of the main _hyperHTML_ goal was _not to ask to learn anything new_.
Technically you just bind it to a DOM context and you start injecting templates with data.
Arrays are resolved, so are DOM nodes, text, and Promises so that all the extensions here work already out of the box.
Once hooked within the main parsing logic performance also could be affected, yet I think this is something missing that I might borrow, using a different implementation, in the near future.
As Summary
If anyone would like to ask or know more about how things are different or why, I'd be happy to provide as many details as needed.
If somebody pushing standards would like to ask the opinion of people already producing Web products with this pattern, that'd be a good way to collaborate.
Best Regards
to be honest, this looks like a half baked clone of hyperHTML and I'm surprised there was no mention whatsoever to such library, or its author, that I think "inspired" 90% of this project ... anyway ...
Well, like I said comparisons are tricky. As for the genesis of lit-html, if it seems like a clone, that's unfortunate, because it's honestly not, but in the realm of open source software and especially DOM creation libraries, there are hundreds of variations on very similar ideas.
For sure, there are a lot of template literals libraries, though hyperHTML seems the most similar to lit-html. I didn't know a whole lot about how hyperHTML worked when I started, because I looked over a bunch of similar ideas (bel, t7, hyperx, E4H, a lot of abandoned libraries on npm...), and I didn't quite understand at first glance how hyperHTML worked. At a cursory glance, it didn't seem like anything did exactly what I wanted to do. I didn't know that hyperHTML used template elements under the hood, for instance, when I started lit but I'm happy to see that there are now two libraries that do that.
I think we need multiple attempts to hone these ideas. I like to think that we're creating an easy to understand and simple API, in a small and fast library, and that the best of the individual ideas contained within the libraries out there will flourish. Maybe another one will come along soon too. For now, I want to see how good I can make lit-html itself.
As for specific comparisons, I have a few responses:
it's not as cross browser as hyperHTML is. There are clear choices in the design that require un-polyfillable features such Symbols while hyperHTML works on IE9 and old Mobile Browsers just transpiling the template literal bit, which is technically the only thing that needs to be transpiled, if needed, and Babel does a very good job there
We only use Symbols for detecting Iterables, and they're trivially polyfillable for that purpose. We've yet to stress lit-html through all the environments we will eventually support, through we'll probably focus on the same support matrix that Polymer has, which doesn't include IE9.
also partial layouts seems to be missing. Try to use html
nope on browsers that don't support template and you'll see empty holes in tables
We will definitely have to test this...
it doesn't let you inject html if needed. Only textContent can be used
This is a feature - we get some protection against XSS this way. Many other libraries make you go out of your way to bind to HTML, ie React's dangerouslySetInnerHTML. But you can interpolate nodes easily:
const div = document.createElement('div');
div.innerHTML = '<span>hi</span>';
html`${div}`;
you need third parts extension to create basic lists or you need a render function per each single template. This can be a limit, it was a limit for me when using highlightjs for code examples
I'm not sure what you're saying here. Arrays and Iterables are supported out-of-the-box, and the repeat directive gives keyed node reuse.
it doesn't fully understand attributes. It uses only setAttribute which might not produce the desired behavior if the attribute is inherited and/or boolean. You cannot
lit-html doesn't have any whitelists and it's likely to stay that way. For boolean attributes we can have a toggle directive:
html`<div hidden=${toggle(someBool)}></div>`
it apparently supports partial attributes, which is intentionally not supported in hyperHTML because it's slower, performance wise, and it gives false idea that an attribute can be partially updated. On top of that, it confuses more 'cause attributes must be in quotes and stuff like this wouldn't look right ... imo, a bit eyes-hurting
That's a fine choice for hyperHTML to make. We've made a different one. Attributes don't need to be included in quotes in lit-html, this works fine:
html`<input value=${v}></input>`
events are not supported so creating components isn't straight forward as it is for React and hyperHTML, you need extensions for standard events like an onclick too.
Events and properties are supported in lit-extended. The core of lit-html only supports very unopinionated features, so only attributes and text node.
Usage of extensions here is a very nice idea but it also means developers need to learn something else beside the rules to create valid templates and the signature to render them.
This is a choice too. When we look at what could be standardized, support for setting properties, or declarative event handlers seems less likely than just attributes, text and a powerful extension point. Proving that extensions can handle use-cases like this is quite important then.
The shape of the extension points in lit comes out of a previous conversation on template extensions we've had: https://github.com/whatwg/html/issues/2254
I suspect that most developers wouldn't need to use something like lit-extended directly, but will use a component base-class that integrated extensions for them.
Arrays are resolved, so are DOM nodes, text, and Promises so that all the extensions here work already out of the box.
All those features are built into lit-html core as well.
Attributes don't need to be included in quotes in lit-html
Gotta test if IE would accept attr={{}} and I also wonder how are you dealing with SVGs which don't seem to be supported as well, another difference I forgot to mention.
Here thousands of SVGs as demo.
More on unquoted attributes, would the following produce a className==="a b" ?: <div class=${'a'}${'b'}>
All those features are built into lit-html core as well.
Sort-of. You need directive, which I'm not sure I understand are a global scope pollution or a module one, but you need to use them to have these behaviors.
In hyperHTML if it's an iterable, you don't need to specify it's an iterable, you just let hyperHTML realize how to deal with the iterable.
I didn't know that hyperHTML used template elements under the hood, for instance
The initial post is on the 5th of March. .Net magazine published a whole article about hyperHTML and it's been the fastest HNPWA since the beginning, the only Polymer competitor.
I trust you didn't know much about it, but it's honestly quite hard to believe. I do agree on one point thought:
I think we need multiple attempts to hone these ideas. I like to think that we're creating an easy to understand and simple API, in a small and fast library, and that the best of the individual ideas contained within the libraries out there will flourish.
Yes, it is nice to have multiple takes and maybe trash all our work in favor of a standard candidate but that's also exactly what didn't sound great to me: 'cause you're at Google you have easier way to push standards and yet after me clarifying to you what was _hyperHTML_ more than a month ago, you never even asked me a question about it but you wrote on the README that you are planning to standardize "your" _lit_ ideas.
This was the thing that wasn't cool at all Justin, the rest is fine.
P.S. Symbols are not possible to polyfill and you cannot partially polyfill them or all other libraries testing typeof Symbol will have issues. Same for WeakMaps. The old polyfill used by Polymer has always been problematic on objects deep cloning, as example.
FYI I am updating this post with differences that I've previously forgotten.
https://github.com/PolymerLabs/lit-html/issues/32#issuecomment-320800997
I've also opened a discussion in _hyperHTML_ repository about ideas that might be adopted by _hyperHTML_ too.
https://github.com/WebReflection/hyperHTML/issues/79
I'm not sure how productive continuing this discussion will be, but there are some inaccuracies about lit-html I wanted to correct.
Attributes don't need to be included in quotes in lit-html
Gotta test if IE would accept
attr={{}}
That works fine in IE11
More on unquoted attributes, would the following produce a
className==="a b"?:<div class=${'a'}${'b'}>
Nope. If you wanted that you would need quotes: <div class="${'a'} ${'b'}">. Quotes are optional in many cases, needed in others, much the same as HTML.
All those features are built into lit-html core as well.
Sort-of. You need directive
No. Nodes, nested templates, iterables, Promises are all handled in lit core. You can see some example tests here: https://github.com/PolymerLabs/lit-html/blob/master/src/test/lit-html_test.ts#L130 and https://github.com/PolymerLabs/lit-html/blob/master/src/test/lit-html_test.ts#L163 and https://github.com/PolymerLabs/lit-html/blob/master/src/test/lit-html_test.ts#L223
In
hyperHTMLif it's an iterable, you don't need to specify it's an iterable, you just lethyperHTMLrealize how to deal with the iterable.
Same with lit-html
Yes, it is nice to have multiple takes and maybe trash all our work in favor of a standard candidate but that's also exactly what didn't sound great to me: 'cause you're at Google you have easier way to push standards and yet after me clarifying to you what was _hyperHTML_ more than a month ago, you never even asked me a question about it but you wrote on the README that you are planning to standardize "your" _lit_ ideas.
This was the thing that wasn't cool at all Justin, the rest is fine.
I might have a little easier access to some people who write standards, but all I'm doing here is thinking of how to limit and layer lit-html so that some concepts might be more likely to be acceptable to standards committees. I'm just thinking ahead. That's why property setting, declarative event handling, and node recycling aren't in core - because they represent opinions that I'm betting would cause too much disagreement in a standards setting. The start of lit-html came from us discussing https://github.com/whatwg/html/issues/2254 in the context of JS and HTML modules, so that's obviously something I kept in mind when designing the layering.
I'm not trying to claim ownership of the ideas here, or saying that "mine" need to be standardized. I'm simply using the (pretty small, really) experience I've had with some of the standards people to try to predict what minimal feature set(s) would be amenable to standardization. That why there's the focus on extensibility.
Also note, that the idea of putting placeholders in a template a pulling them out into parts is not new. Polymer core has essentially worked this way for years. We also discussed it in 2254 and Ryosuke Niwa from Apple implemented a sketch in January: https://bug-167135-attachments.webkit.org/attachment.cgi?id=299053 And of course using JS template literals to produce HTML is not new, there have been libraries doing that for years. So it shouldn't be surprising that the two ideas are combined, and by more than one person.
I wasn't quite aware how similar hyperHTML was to what I started building at the beginning, but I'm not I would have or should have stopped if I did, or if that would have been better for anyone. lit-html and hyperHTML for all their similarities do some things very differently, and have some different capabilities and APIs. Those wouldn't have been uncovered if I hadn't worked on this.
P.S. Symbols are not possible to polyfill and you cannot partially polyfill them or all other libraries testing
typeof Symbolwill have issues. Same for WeakMaps. The old polyfill used by Polymer has always been problematic on objects deep cloning, as example.
The only this we use Symbols for is testing whether an object is an iterable. If Symbols don't exist, then neither do iterables.
I'm not sure how productive continuing this discussion will be
It is, it's a comparison between two developers reaching similar solution, right?
That works fine in IE11
Yeah, tested already in IE9 too. Although, _hyperHTML_ uses less predictable output.
What's the plan to enable text like {{}} inside a pre content, as example?
I'm wondering if that's just a placeholder that needs a more unique name in the near future.
No. Nodes, nested templates, iterables, Promises are all handled in lit core.
I need to read more about then, because if that's the case, I don't understand what's a repeat() about.
I'm also not sure if same list of objects will trash previous layout when a .push({new:"object"}) happens or not. Just curious, with _hyperHTML_ you can wire objects to specific templates too.
I might have a little easier access to some people who write standards
That's a very humble statement. Truth is, you work at Google, so you are already a potential TC39 contributor by default and influential to the Web thanks to WHATWG where many of your colleagues are in it.
Meanwhile, I'm doubling-down on Open Source these days, meaning that instead of receiving any kind of help or hint from a big interested player, I now have to compete with it: Google Polymer lab and full-time Google payed engineers bring it on !!!
As long as it's fair ... becaue putting a "_we're going to standardize this_" in the README, for a thing practically not even ready for production, was a very good move to kill any other attempt around template literals to make it even better attempts than _lit-html_ implementation, isn't it?
The start of lit-html came from us ...
To be honest, that discussion looks more like like mustache templates to me.
The first comment about using template literals comes after my March post on _hyperHTML_ and not before June there's interest on the JS looking template proposal.
I'm simply using the (pretty small, really) experience I've had with some of the standards people to try to predict what minimal feature set(s) would be amenable to standardization.
That's great. Although, are you talking with non googlers that used "your idea" before you created this repository?
focus on extensibility
I've proposed extensibility without needing scope pollution, and only thanks to this alternative project so competition does good things anyway.
We also discussed it in 2254 and Ryosuke Niwa from Apple implemented a sketch in January
I am part of few Web related W3C working groups and nothing like this came to my inbox.
What's discussed in there is not about unique template literals behavior, which was the real and only opened door for both hyperHTML and lit-html: that list of statics you can check on a Map is awesome, isn't it?
That's the real key to this pattern, and I'm sure we had a quite possibly a very similar "_A-HA_" moment there.
Those wouldn't have been uncovered if I hadn't worked on this.
Very true, the standardizing bit is still not as fair as your other statements.
If Symbols don't exist, then neither do iterables.
Array existed before Symbols, but again ... I am talking about compatibility.
You stated lit-html targets are the same of Polymer, I've decided to reach every other too.
Anyway, to stop this conversation, if you like, I just hope after me explaining hyperHTML to you the 29th of June, the day you created later on this repository, a mention to a 6 months older alternative based on exact same solution would've found a place in your README.
Regardless, _lit-html_ will find place on my documentation once ready, don't doubt about that.
Best Regards
P.S. Next up: HyperHTMLElement class with observedAttributes magic.
That's why property setting, declarative event handling, and node recycling aren't in core - because they represent opinions that I'm betting would cause too much disagreement in a standards setting.
Just re that, I think property setting should be reconsidered for core. I have a few reasons for this.
Firstly, properties give you the ability to interleave complex data types. Though attributes are closer to "HTML", properties generally reflect to attributes, and can quite simply within the context of a custom element. There's use cases for only setting attributes, so I can see why this would be contentious. Maybe there's a happy path here. I'd very much like to see a way to pass around complex data types, declaratively using standard native platform APIs. This brings me to my second point.
The second point is less technical, but more political (for better or worse). Two of the biggest complaints I've seen against "the platform" (and conflated with a solution web components should provide) from other communities (namely React) are:
Maybe an alternative is to spec a way to specify a custom setting algorithm.
I think there's potential for a lot of buy in from other communities if a case can be made for them, so, FWIW, I think it's worth reconsidering, or at the very least, discussing. Happy to do it offline, or in another issue.
/2c
Firstly, properties give you the ability to interleave complex data types
Not only. <input value="${data}"> cannot be set through setAttribute once data changes.
document.body.innerHTML = '<input value="1">';
// type manually 2 in the input
document.body.firstChild.setAttribute('value', '3');
// see that input still has 2
This is solved in hyperHTML thanks to smarter property management, so if lit proposes to standardize this setAttribute only based proposal, the proposal itself will be way less useful than it could be.
Boolean for attributes such disabled, deferred, async, or attributes without values such download are also cut out from this implementation.
On top of that, having setAttribute as general mechanism means that onclick, which is just an attribute, will set the listener as string destroying completely its meaning.
No way to declaratively pass around data structs in HTML
This one itself would probably be a hell of a change and historically the best attempts to do that were dataset, as form of data-name serializable content, still a string, and detail in the CustomEvent specification, the only property that accepts and transports any data, even unserializable (but not cross realm).
I don't think it's a template role to define such mechanism, so probably this specific request is out of scope, unless a special meaning to <p data=${{ahy:"object"}}></p> is used (for which I'd say "_why not_", thinking about an ondata listener too)
/2c
@treshugart I think this is better discussed in another issue.
馃憤 no worries. Thought I was clear about that :)
To whoever is/was interested, I've written down the current-status comparison (and filed 3 bugs while doing so)
https://gist.github.com/WebReflection/fadcc419f5ccaae92bc167d8ff5c611b
I'll try to keep it updated as I can. If there's anything missing, ping me.
Most helpful comment
to be honest, this looks like a half baked clone of
hyperHTMLand I'm surprised there was no mention whatsoever to such library, or its author, that I think "inspired" 90% of this project ... anyway ..._viperHTML_ is a NodeJS backend version of _hyperHTML_, I think it's hard to standardize the pattern in a way that's useful for both worlds, so I'm curious to know more about the following:
With @marcoscaceres we were also thinking about possible standardization so it'd be great if someone would talk to us, since we've used this pattern for the last 6 months already.
Comparison so far
It's clear this project is still a work in progress but if somebody would like to know differences as of today with _hyperHTML_ only, 'cause it cannot be compared with _viperHTML_ at this point, these are the main things I've figured out going through the code:
html<td>nope</td>on browsers that don't support template and you'll see empty holes in tablestextContentcan be used, you need third parts extension to create basic lists or you need a render function per each single template. This can be a limit, it was a limit for me when using _highlightjs_ for code examplessetAttributewhich might not produce the desired behavior if the attribute is inherited and/or boolean. You cannot<button disabled="${isDisabled}">as example, so it's half useful with forms and other cases with special attributes<span attr="a ${"b"} ${'c'} ${"d"}"></span>... imo, a bit eyes-hurtingonclicktoo. With _hyperHTML_ events are always DOM Level 3 with auto removal when changed or nullified and no conflict with DOM Level 0. You own the template, you own the events.About extensions
Usage of extensions here is a very nice idea but it also means developers need to learn something else beside the rules to create valid templates and the signature to render them.
One of the main _hyperHTML_ goal was _not to ask to learn anything new_.
Technically you just bind it to a DOM context and you start injecting templates with data.
Arrays are resolved, so are DOM nodes, text, and Promises so that all the extensions here work already out of the box.
Once hooked within the main parsing logic performance also could be affected, yet I think this is something missing that I might borrow, using a different implementation, in the near future.
As Summary
If anyone would like to ask or know more about how things are different or why, I'd be happy to provide as many details as needed.
If somebody pushing standards would like to ask the opinion of people already producing Web products with this pattern, that'd be a good way to collaborate.
Best Regards