diff --git a/README.md b/README.md index aa84781..12b3a60 100644 --- a/README.md +++ b/README.md @@ -225,6 +225,10 @@ Choo comes with a shared state object. This object can be mutated freely, and is passed into the view functions whenever `'render'` is emitted. The state object comes with a few properties set. +When initializing the application, `window.initialState` is used to provision +the initial state. This is especially useful when combined with server +rendering. See [server rendering](#server-rendering) for more details. + ### `state.events` A mapping of Choo's built in events. It's recommended to extend this object with your application's events. By defining your event names once and setting @@ -295,8 +299,8 @@ To can navigate routes you can emit `'pushState'`, `'popState'` or `'replaceState'`. See [#events](#events) for more details about these events. ## Server Rendering -Choo was built with Node in mind. To render on the server call `.toString()` on -your application. +Choo was built with Node in mind. To render on the server call +`.toString(route, [state])` on your application. ```js var html = require('choo/html') @@ -314,6 +318,25 @@ console.log(string) // => '
Hello Node
' ``` +When starting an application in the browser, it's recommended to provide the +same `state` object available as `window.initialState`. When the application is +started, it'll be used to initialize the application state. The process of +server rendering, and providing an initial state on the client to create the +exact same document is also known as "rehydration". + +For security purposes, after `window.initialState` is used it is deleted from +the `window` object. + +```html + + + + + + + +``` + ## Optimizations Choo is reasonably fast out of the box. But sometimes you might hit a scenario where a particular part of the UI slows down the application, and you want to diff --git a/index.js b/index.js index 86910aa..98fa41b 100644 --- a/index.js +++ b/index.js @@ -45,7 +45,16 @@ function Choo (opts) { // properties that are part of the API this.router = nanorouter({ curry: true }) this.emitter = nanobus('choo.emit') - this.state = { events: this._events } + + var events = { events: this._events } + if (this.hasWindow) { + this.state = window.initialState + ? xtend(window.initialState, events) + : events + delete window.initialState + } else { + this.state = events + } // listen for title changes; available even when calling .toString() if (this._hasWindow) this.state.title = document.title