Building fast applications is a tricky challenge. Usually you want to optimize the time to first render and then make sure the page becomes interactive quickly. And once that's done, you want it to all keep feeling snappy. And then some.
Server rendering is a technique to improve time to first render in applications that rely on JavaScript to update the DOM. Instead of waiting for JavaScript to render in the client, it figures out what the DOM should look like on the server. The server then sends the right HTML to the client, so the first render happens instantly.
Choo was built with both Node and the Browser in mind. One of its main features is that it works in any environment. Let's dig in to look at what that looks like.
note: all of this is available out of the box in choojs/bankai. We recommend using Bankai if you're looking for a solution to Server Rendering. However, even if you end up using a prebuilt solution, it can still be useful to know how the underlying mechanisms work.
The main method to use in Choo for server rendering is .toString(routeName)
.
Using it looks something like this:
var html = require('choo/html')
var choo = require('choo')
var app = choo() // 1.
app.route('/', (state, emit) => { // 2.
return html`
<body>Hello humans</body>
`
})
var dom = app.toString('/') // 3.
console.log(dom)
.toString(route)
, and it returns a string. The resulting string will be
'<body>Hello humans</body>'
.There hasn't been too much going on so far. Instead of rendering to the DOM,
we've been creating strings instead. However, what's often the case with server
rendering is that you need some data passed in for your initial rendering.
Luckily the .toString()
method accepts a second argument: state
. Let's see
how this works.
var html = require('choo/html')
var choo = require('choo')
var app = choo()
var state = { message: 'doggos' } // 1.
app.route('/', (state, emit) => { // 2.
return html`
<body>Hello ${state.message}</body>
`
})
var dom = app.toString('/', state) // 3.
console.log(dom)
state
object with some values in it.<body>
element. It takes a value from the state
.state
object to app.toString()
as the second argument. It
returns a string of <body>Hello doggos</body>
.In JavaScript the term "isomorphic code" often refers to code that can run in
both Node and the Browser. For Choo code to be isomorphic, it should render in
the browser, and should export the app
instance in Node so it can be called
for server rendering.
The .mount()
method does just that; in the Browser it will mount the app on
the selector provided to it. Whereas in Node, there is no DOM and Choo knows
this, instead it will remember what selector was used and return the app
instance.
The "classic" version assumes we use require()
for our application.
var choo = require('choo')
var app = choo()
app.route('/', () => html`<body>hello world</body>`)
module.exports = app.mount('body') // 1.
<body>
tag (if in the Browser) and return the
app instance.The import
keyword is what's going to be used to load JavaScript modules in
the near future. It already works in Node, but isn't quite prevalent yet.
Because the details of import
are different from require
, using it requires
a slightly different approach.
import html from 'choo/html'
import choo from 'choo'
var app = choo()
app.route('/', () => html`<body>hello world</body>`)
export default app.mount('body') // 1.
<body>
tag (if in the Browser) and return the
app instance.Websites generally consist of 3 main elements: paragraph text, lists and forms. While paragraph text is generally straightforward to place on a page, lists and forms require some more work. This section explains everything you need to know to work with forms in Choo.
Connecting to the network is essential for applications. This section is all about the browser's network APIs, and how to use them in Choo.
Choo is built up out of two parts: stores and views. In order to render a view,
it must be added to the application through app.route()
. This is the router.
Server rendering is an excellent way to speed up the load time of your pages. This section shows how to effectively render Choo apps in Node.
State machines are a great way to manage different states in your application. In this section we'll learn how to use and implement state machines.
Stores are Choo's data abstraction. They're meant to both hold application data, and listen for events to change it. In traditional systems this is sometimes also known as "models".
Views are Choo's rendering abstraction. It's the part that takes the internal state and renders elements to the DOM.