choojs / choo

:steam_locomotive::train: - sturdy 4kb frontend framework
https://choo.io/
MIT License
6.78k stars 595 forks source link

add SSR hyperscript support #634

Closed ungoldman closed 6 years ago

ungoldman commented 6 years ago

Hello!

There's been some discussion on IRC about figuring out ways to support hyperscript as a bel alternative when using choo.toString in a server context.

Problem

In a non-browser context, objects returned by hyperscript have a toString method that differs from pelo's toString method. So currently hyperscript doesn't work in this context.

Proposal

After doing some investigating, it seems like the easiest way to support hyperscript on the server in choo is to check for outerHTML and return that before trying to use the toString method returned by pelo.

Context, Research

Element.outerHTML is already a standard feature of the DOM spec that returns the stringified HTML fragment of an element. There's also already a toString() method on there that I believe it inherits from Object.toString, which is the thing that usually returns a very unhelpful string like [object Object].

While my first impulse was to see how hard it would be to modify hyperscript to present choo with a toString method that does the same thing as pelo().toString(), it turns out the object hyperscript's factory function returns in a non-browser context is an instance of https://github.com/1N50MN14/html-element, which is already attempting to comply to the standard Element spec mentioned before.

Proposed solution

With all that info in mind, I think it's easiest to modify one line in choo to check for outerHTML first.

Here's the context:

https://github.com/choojs/choo/blob/6bee7086bc0534d46ebad4a6479edf1f6feb207e/index.js#L188-L199

And I think replacing return html.toString() with something like this would do the trick:

return html.outerHTML || html.toString()

I don't think there's a chance outerHTML would be falsey, but we could also do something more defensive like this:

return typeof html.outerHTML === 'string' ? html.outerHTML : html.toString()

If this sounds alright to choo maintainers I'll open a PR.

This is a dog

yoshuawuyts commented 6 years ago

Sounds :100: