DEV Community

Ben Halpern
Ben Halpern

Posted on

Hyperscript Tagged Markup (HTM): JSX alternative using standard tagged templates, with compiler support.

This is an interesting library by @_developit, creator of Preact.

GitHub logo developit / htm

Hyperscript Tagged Markup: JSX alternative using standard tagged templates, with compiler support.

HTM (Hyperscript Tagged Markup) npm

hyperscript tagged markup demo

htm is JSX-like syntax in plain JavaScript - no transpiler necessary.

Develop with React/Preact directly in the browser, then compile htm away for production.

It uses standard JavaScript Tagged Templates and works in all modern browsers.

htm by the numbers:

๐Ÿฃ < 600 bytes when used directly in the browser

โš›๏ธ < 500 bytes when used with Preact (thanks gzip ๐ŸŒˆ)

๐Ÿฅš < 450 byte htm/mini version

๐Ÿ… 0 bytes if compiled using babel-plugin-htm

Syntax: like JSX but also lit

The syntax you write when using HTM is as close as possible to JSX:

  • Spread props: <div ...${props}> instead of <div {...props}>
  • Self-closing tags: <div />
  • Components: <${Foo}> instead of <Foo> (where Foo is a component reference)
  • Boolean attributes: <div draggable />

Improvements over JSX

htm actually takes the JSX-style syntax a couple steps further!

Here's some ergonomic features you get for free thatโ€ฆ




Compared with JSX:

  • No transpiler necessary
  • HTML's optional quotes:
  • Component end-tags: <${Footer}>footer content<//>
  • Syntax highlighting and language support via the lit-html VSCode extension and vim-jsx-pretty plugin.
  • As of 2.0.0, htm is stable, well-tested and ready for production use.

Discussion (28)

Collapse
mvasigh profile image
Mehdi Vasigh • Edited on

It seems like the biggest win here is not having to use a transpiler, though I feel like most projects would already have Babel in there. Other than that, not sure if this buys the developer anything that JSX doesn't since the syntax is still somewhere in between HTML and JSX. However, cool and interesting approach!

Collapse
embiem profile image
Martin Beierling-Mutz

You still need babel if you want to compile it for production, to get rid of the extra bytes.

To me, the benefit of actually using it in existing Preact/React code is that it is actually much closer to HTML. Being able to use class instead of className is nice :)

Collapse
mvasigh profile image
Mehdi Vasigh

What I meant is that either way you are taking a bunch of markup syntax and translating it to React.createElement() calls. Whether you import a library function and do that work there or let a Babel plugin do the work, it's up to you. The latter is a bit cleaner IMO but it requires a transpile step. If you're doing that anyway then may as well use JSX.

Thread Thread
embiem profile image
Martin Beierling-Mutz

Yes exactly, in most build setups using HTM will be compiled just like JSX is.

After thinking about it a bit more, these are my reasons why to use HTM over JSX:

  • it's less magic, as you can see that it's a Tagged Template
  • because of less magic, it's also more beginner friendly
  • it's closer to HTML, without JSX limitations like class/className

And the biggest reason: no build step! I mean, look at the example... it's a 3.7KB js dependency and you can build preact apps!

To me, this is a taste of the future. A future where build tools won't be necessary anymore. Until then, we still need to transpile, code-split, optimize etc. using build/bundle tools like webpack.

Collapse
ben profile image
Ben Halpern Author

Yeah. In most cases these days, the transpiler is a given. However, I could imagine a lot of circumstances where evaluating without transpiration is much more convenient. Enough so to possibly drop the need for jsx altogether.

Had these two things come along at the same time, good chance we don't bother with the rigmarole of jsx.

Collapse
wolfhoundjesse profile image
Jesse M. Holmes

If Babel isn't necessary, I wonder what would happen under the hood if you bundled a new project with Parcel.

Collapse
vonheikemen profile image
Heiker

No transpiler necessary

This is it for me. That is the benefit. I believe that is one of the reasons Vue got so many beginners excited about frontend. You could start learning about the framework without introducing any of the noice of modern tooling.

I learned about React a couple of years ago, when I first heard the term "transpiler" it made want to skip it (and I did). It took me a year and half (and working with node) to gather the confidence to finally tackle this "transpiler" thing (A.K.A. babel and his friend webpack) Even after learning how to use it I hated it.

Collapse
bennypowers profile image
Benny Powers ๐Ÿ‡ฎ๐Ÿ‡ฑ๐Ÿ‡จ๐Ÿ‡ฆ

Try LitElement, and you'll get templating AND component model using built-in features.

dev.to/bennypowers/lets-build-web-...

Collapse
vonheikemen profile image
Heiker

Thanks for the link. Now I'm interested.

Do you know if lit-html works with JSDOM? I would to make test like this one during development.

Thread Thread
bennypowers profile image
Benny Powers ๐Ÿ‡ฎ๐Ÿ‡ฑ๐Ÿ‡จ๐Ÿ‡ฆ

I've had some peripheral issues like javascript module support with jsdom

But barring those kinds of problems (which are, to be clear, problems with node-based tools not able to run browser-standard JavaScript), you should be golden.

You might consider karma, or puppeteer or Cypress for browser testing, since those tools will actually run your cove in the environment you are targeting.

open-wc.org/recommendations/testin...

Collapse
qm3ster profile image
Mihail Malo

I see this opinion all around and don't get it at all.
One of the best features of Vue for me is single-file-components, which of course necessitate a bundler.
The "full build" option that allows templating at runtime seems like cruft that I would rather development time wasn't spent oh.

Collapse
vonheikemen profile image
Heiker

To me is more about the learning phase (from a beginner perspective). You can play around with Vue even if you don't know anything about bundlers. If the learning experience is pleasant then people will be encourage to dig deeper. Eventually they will get to the "advance" stuff, but hopefully they get there with enough confidence in their knowledge and see it as "just another step".

Thread Thread
qm3ster profile image
Mihail Malo

I guess this can help adoption when someone is really just using notepad and a browser.
But for me the best way to "try a framework" was always
git clone framework-start-example test or pnpx framework-cli init test
followed by cd test && pnpm i && pnpm run dev with hot reloading and stuff.

Thread Thread
vonheikemen profile image
Heiker

notepad and a browser.

That's my jam. Replace notepad with Sublime text and you basically described my development environment when I started learning. It would be awesome if I could work just using those two.

Now that I think about it, it is sad that CLI tools and boilerplate code is the "new normal" when you create client side javascript.

Anyway, when trying anything javascript related my favorite way is using codepen (the notepad of javascript online editors).

Thread Thread
qm3ster profile image
Mihail Malo

I don't find it sad at all. It's a huge relief for me.
How do you feel about codesandbox.io?

Collapse
jsn1nj4 profile image
Elliot Derhay

So long as the file extensions don't become .htm ;)

Collapse
kip13 profile image
kip

What are the differences with lit-html ?

Collapse
ben profile image
Ben Halpern Author

From what I'd gather:

htm is looking to act as a convenient alternative to jsx to fit the workflow of folks in react/preact land. lit-html is more of a whole new thing that is technically similar, but not coming from the same place in terms of developer experience.

One other difference in practical terms

htm:

As of 2.0.0, htm is stable, well-tested and ready for production use.

lit-html:

lit-html is currently in development. It's on the fast track to a 1.0 release, so we encourage you to use it and give us your feedback, but there are things that haven't been finalized yet and you can expect some changes.

Collapse
abraham profile image
Abraham Williams

lit-html has an RC release and is expecting a 1.0 release in January.

Another potential perk of lit-html is it's backed by a team of developers at Google and is well tested by being used in Polymer/LitElement.

Collapse
bennypowers profile image
Benny Powers ๐Ÿ‡ฎ๐Ÿ‡ฑ๐Ÿ‡จ๐Ÿ‡ฆ

lit-html has no VDOM overhead

Collapse
equinusocio profile image
Mattia Astorino • Edited on

And is made to build web components platform compliant, not abstractions.

Thread Thread
bennypowers profile image
Benny Powers ๐Ÿ‡ฎ๐Ÿ‡ฑ๐Ÿ‡จ๐Ÿ‡ฆ

Good point. You won't have the same kinds of issues with event listeners and losing references to DOM

Collapse
kayis profile image
K (he/him)

I'm torn.

On the one side it works without pre-compilation, on the other hand nobody deploys stuff without pre-compliation these days anyway.

On the one hand it has the shorter end-tag syntax, on the other hand most components have short names anyway.

<Text>Hello</Text>
h`<${Text}>Hello<//>`

<VeryLongComponentName>Hello</VeryLongComponentName>
h`<${VeryLongComponentName}>Hello<//>`

<List><Item>1</Item><Item>2</Item><Item>3</Item><Item>4</Item<Item>5</Item></List>
h`<${List}><${Item}>1<//><${Item}>2<//><${Item}>3<//<${Item}>4<//><${Item}>5<//><//>`

I think, the end-tags are a bit harder to read and with many short components it leads to more typing.

But I think this is a small price to pay for getting rid of tanspiling in PoCs or such.

Collapse
ozzyogkush profile image
Derek Rosenzweig

interesting. didnt know about template functions, that's pretty cool!

Collapse
david_j_eddy profile image
David J Eddy

This looks interesting. I do like the Component end-tags. :)

Collapse
aafrey profile image
aafrey

Also check out Bel, Yo-Yo, and nanohtml packages on npm. All make use of tagged template literals instead of jsx

Collapse
sultan99 profile image
Sultan

I can suggest another helper library which allows easy to use React without JSX.
github.com/sultan99/react-on-lambda