Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Why must text nodes be created explicitly? #1009

Closed
ghost opened this issue Jan 11, 2021 · 3 comments
Closed

Why must text nodes be created explicitly? #1009

ghost opened this issue Jan 11, 2021 · 3 comments
Labels
meta News and communication

Comments

@ghost
Copy link

ghost commented Jan 11, 2021

Hi there,

Thank you for all your thoughtful work and sharing it with the world. I'm inspired by the discipline and thoughtfulness put into your projects like superfine and hyperapp.

Having used some other hyperscript implementations with various degrees of convenience, I wonder why text nodes must be created explicitly using superfine. Couldn't it be inferred with a simple typeof check?

One reason I ask is I'd like to use something like developit/htm to generate hyperscript from tagged template literals. While hyperscript has its benefits, I find it more convenient and natural to work with html using strings in some cases, e.g. integrating with a third-party design system.

Thanks for the handy library and your insight!

@jorgebucaran jorgebucaran transferred this issue from jorgebucaran/superfine Jan 11, 2021
@zaceno
Copy link
Contributor

zaceno commented Jan 11, 2021

@hqproto
Like you said, it could be inferred with a typeof check. But hyperapp would have to process the entire vnode tree recursively looking for things that might be strings to turn in to text nodes. It's not a huge performance hit but still – considering the person authoring the view already knows, and can tell us explicitly what should be a text node, why waste those cycles?

Of course, not everyone prefers writing explicit hyperscript, but that's no problem! LIke you said it's a simple typeof check you can do in userland.

You can make your own h function that does that and whatever else is needed (collecting multiple children in to an array, flattening children) for JSX or htm. Just base it on hyperapp's original h and text functions, and bind your own h in htm's .bind(...) rather than hyperapp's and youre good.

By the way:

there is another issue with using hyperapp (and presumably superfine) with htm, and that is the fact that htm's caching conflicts with a performance optimization in hyperapp. Hyperapp expects you to give it new vnodes each time (because it mutates the ones you give it) which is not true with the default htm. You need to use the "mini" version of htm (which does not do any caching) to be safe.

As an alternative for Hyperapp you could look in to hyperlit.

(It probably works for superfine as well but it will import hyperapp so probably not what you want in that case)

@zaceno
Copy link
Contributor

zaceno commented Jan 15, 2021

@hqproto if you would still like to use developit/htm (or JSX) for creating hyperapp views, I have published https://github.com/zaceno/hyperapp-jsx-pragma which exports a h function that works like the old, pre-v2.0.5 version did.

For use with htm, for example:

import {app} from 'https://unpkg.com/hyperapp'
import htm from 'https://unpkg.com/htm/mini/index.module.js' //need the mini version because it doesn't cache nodes
import h from 'https://unpkg.com/hyperapp-jsx-pragma'
const html = htm.bind(h)

app({
  init: {},
  view: () => html`
    <body>
      <h1>Hello</h1>
    </body>`,
  node: document.body
})

But again, I recommend using Hyperlit for hyperapps, rather than developit/htm. The primary reason I published hyperapp-jsx-pragma is – as evidenced by its name – JSX

@jorgebucaran
Copy link
Owner

Text nodes are not strings. "This is a string" and text("this is a text node"). It may seem plain, but it isn't from a type perspective. Text nodes and strings are different types. Because it's now up to you to specify text nodes we don't have to worry about it, which allowed us to simplify h quite a bit (we didn't always have a text function).

I'd also argue that using text makes your views more readable. Now you can detect where the text nodes are in a heartbeat and leave strings for what they are, the tag in h("h1"), attributes that expect a string like input({ type: "text" }), etc.

This change was also motivated by performance and size, since less code means fewer bytes and usually (but not always) faster execution. Whenever you use h you're just createVNode(tag, props, children).

Simple is beautiful! 💗

@jorgebucaran jorgebucaran added the meta News and communication label Jan 27, 2021
@jorgebucaran jorgebucaran pinned this issue Apr 3, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
meta News and communication
Projects
None yet
Development

No branches or pull requests

2 participants