Lit-html: Is it possible to replace html syntax with hyperscript or jsx?

Created on 1 Dec 2018  路  7Comments  路  Source: Polymer/lit-html

I love lit-html concepts, simplicity and performance!
To be "perfect" I would like to be able to write this:

    return html`
      <div id='app' class='no-select' style=${style}>
        ${Jumbotron()}
        ${List()}
      </div>
    `;

like this (jsx-like):

    return (
      <div id='app' className='no-select' style={style}>
        <Jumbotron/>
        <List/>
      </div>
    );

or like this (hyperscript-like):

    return (
      h('div', { id: 'app', className: 'no-select', style },
        Jumbotron(),
        List()
      )
    );

But, unfortunately it's not possible to write ES6 tagged templates programmatically as far as I know.

The main benefits I see to write the templates with, for example, hyperscript or jsx are:

  • Code migration / reuse: If you already have React functional components written you can just continue to use them but with no React at all. Lit-html will take care of reconciliation at great speed and developer experience.
  • Better abstractions for other use cases: Being jsx or hyperscript just function calls, you can target the dom (with lit-html) but you can also target other platforms like native-mobile. So, in theory, it will be possible to have the same example above producing <View>, <Text> or any other type of component, because being functions you can just produce whatever you want.

As a programmer I like to separate the _WHAT_ of the _HOW_, so I can evolve the _HOW_ without the need of (necessarily) touching the _WHAT_.

I know this is not an issue but I think may be a good topic to talk about.

Medium

Most helpful comment

@artalar try lit-analyzer which provides type checking for lit-html templates. It works really nice.

All 7 comments

The point of lit-html is to be able to write HTML templates in JS without a required transpiler. Supporting JSX goes against that and is out of scope for this project. There are existing JSX-to-lit-html compilers which you're free to use.

Hyperscript itself is already an option if you use it with a VDOM. For lit-html's approach it's not suitable because it doesn't separate the static and dynamic parts of a template. We need the static strings to build the HTML <template> element just once so we can clone it for instantiation.

Migrating React components to Web Components + lit-html is in scope, and maybe we'll see some tools pop up to do that. I don't want to invest in a lit-html specific component model though, we have Web Components for that.

Thanks, totally agree about avoiding transpilers (except maybe if you have some previous components already written in jsx).

The best possible scenario I think will be to produce tagged template literals programatically, so I can use lit-html as a renderer for html and another renderer for non-web.

Maybe in a future version of ES it will be possible :)

In any case, how does the code produced by tagged template literals look like inside lit? Maybe it will be possible to produce that code with nested function calls?

Lit-html uses the tagged template literal syntax ( ${ }) to determine which parts are static and which parts are dynamic. The problem with the syntaxes you suggest is that they have nothing that indicates which parts of the template are static, and which parts are dynamic. Without this there is no way to determine how to build the static part of the HTML <template> that can be re-used, which is essential for lit-html to work.

You can reproduce the behaviour of tagged template literals with function calls, which is what Babel does when it transpiles templates to ES5, but it looks nowhere as nice as your examples

You must have some kind of syntax that indicates that certain parts are static for the lit-html rendering algorithm to work. You would need something like this:

    // in render()
    return (
      h(appDiv,
        Jumbotron(),
        List()
      )
    );

    // somewhere global
    const appDiv = static('div', { id: 'app', className: 'no-select', style });

Which is close to what Babel does. If you inline the static() function in render() it can never be as efficient as lit-html, because will re-evaluate the static() function call on every render, whereas lit-html never needs to re-evaluate the static parts of the template, because of how tagged template literals work.

If you want to learn more, you can watch this ~1 hour video where I explain the internals of lit-html here:
https://www.twitch.tv/videos/322965922

@justinfagnani @ruphin Thanks a lot for your comments, I am going to take a look at the video later. I am closing this for now.

@justinfagnani @ruphin
lit-html is a great tool, thanks for it!
But template string is impossible to static type checking. Example:

html`<span color=${function totaliInvalid(){}}>${value}</span>`

Example is more evidently with using custom elements by tag:

html`<my-component property=${someValue}></span>`

^ Here typescript is useless and can't do anythink (check compatibility of property and someValue).

JSX works fine with it and perfectly checks all attributes and its values.

So, is it possible to create build-time compiler JSX -> template literals to use the full power of static type checking?

@artalar try lit-analyzer which provides type checking for lit-html templates. It works really nice.

@web-padawan wow! Looks awesome, thanks a lot!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

abdonrd picture abdonrd  路  4Comments

pjtatlow picture pjtatlow  路  3Comments

pmkroeker picture pmkroeker  路  5Comments

dflorey picture dflorey  路  4Comments

justinfagnani picture justinfagnani  路  3Comments