Title Text
ISOMORPHIC APPS:
(JUST) THE GOOD PARTS

@marianodvazquez
github.com/nanovazquez
Isomorphic
Isomorphic JavaScript apps are that run the same code in the client and the server
Isomorphic
Introducción
isomorphic, universal, server-side rendering, client-side rendering
Isomorphic
You heard it here first — within a few years, it will be rare to see an advanced web app that isn’t running some JavaScript on the server.
Isomorphic JavaScript: The Future of Web Apps (2013)


Universal
Universal
Is a term used to emphasize the fact that a particular piece of JavaScript code is able to run in multiple environments
Universal
Using Universal JavaScript means the rendering logic is simply passed down to the client.
Making Netflix.com faster (2015)

BUT
Isomorphic also is the functional aspect of seamlessly switching between client and server side rendering
without losing state
Full client-side rendering

Full server-side rendering

Full server-side rendering

Exercise 0: Client-side app using React + Redux
Scenario:
-
Full client-side app, no SSR
-
PerceivedLoading time at initial render
-
No SEO support
Exercise 1: Server side rendering with React
Challenge:
-
Remove (perceived) loading time at initial render
-
SEO support
-
What about the data?
What about Redux?
To send the data down to the client, we need to:
-
create a fresh, new Redux store instance on every request;
-
optionally dispatch some actions;
-
pull the state out of store;
-
and then pass the state along to the client.
On the client side, a new Redux store will be created and initialized with the state provided from the server.
Redux's only job on the server side is to provide the initial state of our app.
What about Redux?
import path from 'path'
import Express from 'express'
import React from 'react'
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import counterApp from './reducers'
import App from './containers/App'
const app = Express()
const port = 3000
// This is fired every time the server side receives a request
app.use(handleRender)
// We are going to fill these out in the sections to follow
function handleRender(req, res) { /* ... */ }
function renderFullPage(html, preloadedState) { /* ... */ }
app.listen(port)
What about Redux?
import { renderToString } from 'react-dom/server'
function handleRender(req, res) {
// Create a new Redux store instance
const store = createStore(counterApp)
// Render the component to a string
const html = renderToString(
<Provider store={store}>
<App />
</Provider>
)
// Grab the initial state from our Redux store
const preloadedState = store.getState()
// Send the rendered page back to the client
res.send(renderFullPage(html, preloadedState))
}
What about Redux?
function renderFullPage(html, preloadedState) {
return `
<!doctype html>
<html>
<head>
<title>Redux Universal Example</title>
</head>
<body>
<div id="root">${html}</div>
<script>
window.__PRELOADED_STATE__ = ${JSON.stringify(preloadedState)}
</script>
<script src="/static/bundle.js"></script>
</body>
</html>
`
}
What about Redux?
import React from 'react'
import { render } from 'react-dom'
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import App from './containers/App'
import counterApp from './reducers'
// Grab the state from a global injected into server-generated HTML
const preloadedState = window.__PRELOADED_STATE__
// Create Redux store with initial state
const store = createStore(counterApp, preloadedState)
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
Since we have the same initial state for our (client) Redux store the result will be the same real DOM.
Exercise 2: SEO
Challenge:
-
Be a crawler: compare SEO between 2 apps: a SSR and an SPA
-
How can you measure it?
-
Is it useful for you?
Exercise 2: SEO
Fetch as Google!

Exercise 3: initial rendering time & bundles
Challenge:
-
Improve initial rendering time by using bundles
-
Identify tradeoffs

async, defer, attributes
more info here



Bonus track: next.js
For free:
- Server-side rendering and indexing of each ./pages
- That means automatic code splitting :)
- Lifecycle hooks for initial data population
- Error handling
- and other stuff (static folder, error handling, bundling, etc)
A minimalistic framework for universal server-rendered React applications
ISOMORPHIC APPS: (JUST) THE GOOD PARTS
By Mariano Vazquez
ISOMORPHIC APPS: (JUST) THE GOOD PARTS
Repo of the presentation https://github.com/nanovazquez/nodeconf-isomorphic-workshop
- 1,400