Hyperapp: Make container required without exceptions!

Created on 28 Feb 2018  路  10Comments  路  Source: jorgebucaran/hyperapp

The title is deceiving because the container _is_ required according to the documentation and types, so this is not "technically" a breaking change. So, what am I talking about?

app(state, actions, view)

Some of you may be aware that Hyperapp can be used partially "headless", that is, without a DOM. While this may sound like a useful "feature", it's really just a side effect of how we compute the view function. Using Hyperapp as a state manager can be fun, but that's not what this project is about.

\ Hyperapp is for building web applications. If you are building an application that is not based web technologies, then look elsewhere.
\

馃槃

Breaking Wontfix

Most helpful comment

One reason (maybe) to leave the behavior as is wrt the container, is for testing apps (or sub-apps/modules) without the need to include a server-side-dom-library.

If all you need is to verify that actions update the state accordingly, you can just use the view as a trigger to test this. Or if you prefer just assert your views by just deep-equal-checking virtual nodes.

Obviously that's still possible with the rendering engine running. But it's just nice not to engage it and have to set up a fake DOM to avoid errors, if you don't need it.

All 10 comments

I don't know what to tag this issue, so I'll tag it _breaking_ for the time being.

But we need headless version for server-side rendering...

You mean, you need it for hyperapp-render? I server-side render my content and use the default DOM recycling feature in Hyperapp. To this day, I still don't understand what's the point of hyperapp-server and hyperapp-render. If you can explain it, then maybe we could do something.

I am in favor of the headless feature. That go without saying. I am the one who introduced this feature.

I have only one (or two) question. Is #627 issue only about Hyperapp meaning/goal ?
Do you exclude other renderers, that are not DOM-based, from web (Workers, Canvas, D3, WebGL, ThreeJS, Native{Script, Tabriss}, etc...) ?

@Swizz IIRC "headless" was simply a side effect of how we handle/compute the view. You are responsible for proving that it was possible to use Hyperapp without a container, e.g., here, which is better.

Do you exclude other renderers, that are not DOM-based...

Basically, yes. Hyperapp is neither a VDOM or a state manager, is both. That's why.

If your doctrine line is made in steel, and you see this as an undesired side effect. (It is not a bug, it is a feature). So, you can remove it.

I mean by "introduced this feature" the fact that we removed the default document.body behavior to let this bug/feature lives

I server-side render my content and use the default DOM recycling feature in Hyperapp.

How do you do that? Do you write html markup manually on the server and then duplicate it inside your view function for hyperapp?

The purpose of server side rendering is to use the same code on client and server side.
See Isomorphic JavaScript article by Airbnb for detailed explanation.

@hyperapp/render package was made to be able to reuse your application code on server side.
Thus you don't need to write your views twice (as a jsx for hyperapp and as html markup for server).

Next your question could be why do you need SSR why not just use client side rendering only?
I will answer with this video: Server-side Rendering with JavaScript Frameworks.

Okay, next..
What if automatically generate an html markup on the server from your view? Yes, you can:

import { renderToString } from '@hyperapp/render'
const view = () => <h1>Hello World!</h1>
renderToString(view()) // => "<h1>Hello World!</h1>"

Hmm.. But my application is not just a view it also has state and actions.
Can I reuse my state and actions on server side too? Sure:

import { render } from '@hyperapp/render'
const actions = render(app)(state, actions, view)
await actions.fetchPosts()
actions.toString() // => "<main><h1>Posts</h1><ul><li>Dynamic data</li>...</ul></main>"

If we made container mandatory, then we won't be able to use app on server side. I can fix it by copy pasting state management logic from hyperapp to @hyperapp/render but it may lead to inconsistency at some point of time. It is better to always reuse things instead of copy paste.

Also you are saying it is better (easier to develop, maintain and so on) to create multiple small apps than one complex monolithic app with what I totally agree.

The case: I have a game web-application. I use hyperapp to manage and render scenes (lobby, scoreboard, game-canvas, chat, etc.). Game canvas become to complex and I decide to create a separate app for it. But I need only state-management for this app. Now I can use hyperapp as for this. But if container become mandatory I need to include one more state management library to my bundle :cry:

One reason (maybe) to leave the behavior as is wrt the container, is for testing apps (or sub-apps/modules) without the need to include a server-side-dom-library.

If all you need is to verify that actions update the state accordingly, you can just use the view as a trigger to test this. Or if you prefer just assert your views by just deep-equal-checking virtual nodes.

Obviously that's still possible with the rendering engine running. But it's just nice not to engage it and have to set up a fake DOM to avoid errors, if you don't need it.

The people spoke! I'll put it back then. :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jscriptcoder picture jscriptcoder  路  4Comments

Mytrill picture Mytrill  路  4Comments

icylace picture icylace  路  3Comments

ghost picture ghost  路  3Comments

jacobtipp picture jacobtipp  路  3Comments