toString: support rehydration

This commit is contained in:
Yoshua Wuyts
2016-05-24 02:10:17 +09:00
parent 80dca262ad
commit 60665f2a71
8 changed files with 159 additions and 33 deletions
+48 -4
View File
@@ -21,6 +21,7 @@ productive package.
- [keyboard](#keyboard)
- [websockets](#websockets)
- [Rendering in Node](#rendering-in-node)
- [Rehydration](#rehydration)
- [API](#api)
- [FAQ](#faq)
- [Installation](#installation)
@@ -310,9 +311,10 @@ queueing data. You might want to use a package from `npm` or [write your
own][ws-reconnect] if you're building something for production.
## Rendering in Node
Sometimes it's necessary to render code inside of Node; for serving first
requests, testing or other purposes. Applications that are capable of being
rendered in both Node and the browser are called _[isomorphic][isomorphic]_.
Sometimes it's necessary to render code inside of Node; for serving hyper fast
first requests, testing or other purposes. Applications that are capable of
being rendered in both Node and the browser are called
_[isomorphic][isomorphic]_.
Rendering in Node is slightly different than in the browser. First off, to
maintain performance all calls to `subscriptions`, `effects`, and `reducers`
@@ -352,6 +354,45 @@ if (module.parent) module.exports = app
else document.body.appendChild(app.start())
```
### Rehydration
Now that your application is succesfully rendering in Node, the next step would
be to make it load a JavaScript bundle once has loaded the HTML. To do this we
will use a technique called _rehydration_.
_Rehydration_ is when you take the static, server-rendered version of your
application (static HTML, _dehydrated_ because it has no logic) and _rehydrate_
it by booting up the JS and attaching event handlers on the DOM to make it
dynamic again. It's like restoring flavor to cup noodles by adding hot water.
Because we're using something called `morphdom` under the hood, all we need is
point at an `id` at the root of the application. The syntax for this is
slightly different from what we've seen so far, because we're _updating_ a
dehydrated DOM nodes to make them dynamic, rather than a new DOM tree and
attaching it to the DOM.
```js
const choo = require('choo')
const app = choo()
app.router((route) => [
route('/', (params, state, send) => choo.view`
<h1 id="app-root">${state.message}</h1>
`)
])
if (module.parent) module.exports = app
else app.start('#app-root'))
```
When the JS is booted on top of the dehydrated application, it will look for
the `#app-root` id and load on top of it. You can choose any name you like for
the id, but __make sure it's the same on every possible top level DOM node__,
or else things might break. Furthermore to ensure things go smoothly, try and
keep the initial state identical on both the server and the client.
And that's it! If you want to go down the route of mad performance, consider
make all first request static and caching them using something like [bl][bl],
[nginx][nginx], [varnish][varnish] or a global CDN.
## API
### app = choo()
Create a new `choo` app
@@ -404,7 +445,7 @@ for the past year. I originally used `virtual-dom` with `virtual-app` and
`wayfarer` where now it's `yo-yo` with `send-action` and `sheet-router`. The
main benefit of using `choo` over these technologies separately is that it
becomes easier for teams to pick up and gather around. The code base for `choo`
itself is super petite (`~150` LOC) and mostly acts to enforce structure around
itself is super petite (`~200` LOC) and mostly acts to enforce structure around
some excellent npm packages. This is my take on modular frameworks; I hope
you'll find it pleasant.
@@ -535,3 +576,6 @@ $ npm install choo
[module-parent]: https://nodejs.org/dist/latest-v6.x/docs/api/modules.html#modules_module_parent
[sse-reconnect]: http://stackoverflow.com/questions/24564030/is-an-eventsource-sse-supposed-to-try-to-reconnect-indefinitely
[ws-reconnect]: http://stackoverflow.com/questions/13797262/how-to-reconnect-to-websocket-after-close-connection
[bl]: https://github.com/rvagg/bl
[varnish]: https://varnish-cache.org
[nginx]: http://nginx.org/