• Hirshorn Zuckerman
Design Group
• Offices in Rockville,
Baltimore and NY
• ~170 employees
(and growing!)
• We ❤ React and ReactDC
Slide 4
Slide 4 text
• Launched in October of 2014
• One of the first isomorphic
React SPAs in production
• Our (the?) second
• 100s of React components
• 7 committers
Slide 5
Slide 5 text
ISOMORPHIC?
Slide 6
Slide 6 text
“ISOMORPHIC”
• Runs on the server and in the browser
• DRY!
• Saves times
• Prevents bugs
• One language everywhere is good for
building a team that can jump around
Slide 7
Slide 7 text
ISOMORPHIC WHAT?
• Routing
• Data access
• Templating?
Slide 8
Slide 8 text
BENEFITS OF SSR
• Easily read by computers
• SEO
• Speed/UX
• User doesn’t need to wait for app to
download and initialize
• Progressive enhancement makes site
resilient to JS errors
Slide 9
Slide 9 text
DIFFERENT APPROACHES
• Serve rendered HTML → Hydrate → Repeat
• Serve rendered HTML → Hydrate → SPA
WHAT DOES THIS HAVE
TO DO WITH REACT?
• React makes it possible
• Not a goal of React, just falls out of good
functional design
• Ember “FastBoot” announced Dec 22
Slide 20
Slide 20 text
SSR: THE THEORY
function myApp(url):DOM
Slide 21
Slide 21 text
SSR: THE THEORY
• One app (function!) generates entire document
• On server: React.renderToString
• In browser: React.render
Slide 22
Slide 22 text
SSR HURDLES:
• Not all browsers are cool with you using
innerHTML in head
• Different APIs for titles on server and browser
• One solution: server-only logic for wrapping UI
(and adding head)
• Our solution: react-frozenhead
Slide 23
Slide 23 text
SSR HURDLES:
ROUTING
Slide 24
Slide 24 text
ROUTING SOLUTIONS:
REACT-ROUTER-COMPONENT
• Features
• Declare routes in JSX
• Colocate data requirements with any component via
getInitialStateAsync lifecycle method
• But…
• Fibers?
• “React Async is an anti-pattern”
• Made server-side integration tricky
Slide 25
Slide 25 text
ROUTING SOLUTIONS:
REACT-ROUTER
• Features
• Declare routes in JSX
• Based on Ember’s router
• But…
• No SSR solution in sight—certainly not by our launch date
• Looked to be repeating the same mistakes as
react-router-component
Slide 26
Slide 26 text
ROUTING SOLUTIONS:
MONOROUTER
• Features
• Based on express-style routing
• Designed from the ground up to work with SSR
• Generate entire document (including )
• But…
• Very conservative design
• No colocation of data requirements and UI code
Slide 27
Slide 27 text
UPDATE!
REACT-ROUTER
• New API announced November 22
• Takes into account input of Andrey Popp (RRC author)
• Colocate data requirements with Handler/Controller components
(via convention; e.g. static fetchData)
• But…
• Lots needs to be done outside of router (data fetching, , …)
• …maybe that’s a good thing!
• Too late for us…this time
Slide 28
Slide 28 text
SSR HURDLES:
ISOMORPHIC JS
• Getting your app to run in two environments
(isomorphic js)
• Getting your app to create the same document
in both environments
Slide 29
Slide 29 text
SSR HURDLES:
ISOMORPHIC CODE
Slide 30
Slide 30 text
OUR APPROACH:
TWO WEBPACK BUILDS
{
target: 'node',
externals: (
fs.readdirSync(path.resolve('node_modules'))
.map((dir) => new RegExp(`^${ dir }(?:$|\/)`))
),
// ...
}
{
target: 'web',
// ...
}
Slide 31
Slide 31 text
NODE LIBRARIES
• Lots of modules on npm work in the browser
• browserify pioneered “browser”
field in package.son
• Watch out for:
• Packages that access node platform libraries
(mostly I/O stuff)
• File size!
Slide 32
Slide 32 text
BROWSER LIBRARIES
• $.uhoh
• Don’t do browser stuff until
componentDidMount
• Watch out for memory leaks on the server
• Use webpack’s null-loader to avoid running
browser code on the server
Slide 33
Slide 33 text
DATA ACCESS
• Goodbye ORM!
• HTTP allthethings.jpg
Slide 34
Slide 34 text
SSR HURDLES:
DETERMINISM
Slide 35
Slide 35 text
CHECKSUM INVALID??
• Markup generated on server must match DOM
generated in browser
• Usually, you’re rendering components with
different props
• Global state/Flux stores different?
• Circle approximated with
two Bézier curves
• Drawn using math (as a
function of radius, handle
length, stroke width, etc.)
for easy tweaking
• Animating is just a matter of
changing the control points
over time
Slide 39
Slide 39 text
FLOATING POINT MATH!
• Who cares about 0.1 + 0.2?!
• 7 / 3
• 2.333333333333334
• 2.3333333333333335
Slide 40
Slide 40 text
DEALING WITH
NON-DETERMINISM
• Be on the lookout and avoid! (toFixed(), etc)
• Move code to componentDidMount
• only called on client so this is where you can start messing
with state with abandon
• but nothing you do will be in the initial response (sorry,
Google)
• so you don’t do much in it
• “Fossils”
Slide 41
Slide 41 text
REHYDRATION & FOSSILS
• All state used to generate your component tree
must be the same on the server and in the
browser
• Most common solution is to serialize state as
JSON “fossils” which are used to reconstruct
data on the client
• Disclaimer: “fossils” is a term we made up
Slide 42
Slide 42 text
No content
Slide 43
Slide 43 text
...
...
...
Slide 44
Slide 44 text
THE FUTURE?
Slide 45
Slide 45 text
No content
Slide 46
Slide 46 text
?
• Generating the view from the initial request is limiting
• Very little data sent by browsers (viewport size, supported APIs, etc.) and it
can’t be inferred from UAs
• Maybe we could load bootstrapper and get server-rendered view with an
XHR?
• Back in hot water with Google (for now).
Use ?
• Is it worth the effort and drawbacks?
• Debugging story is still awful (facebook/react#2686)
• Google will get there…eventually
Slide 47
Slide 47 text
THE PRESENT!
• The most sane way to develop web apps so far
• Components FTW!
• No SEO sacrifices
• Site feels snappy
• Single-language code base
• No ugly hacks for Google (like traditional SPAs)
• Got a reusable API out of it
Slide 48
Slide 48 text
HZDG.COM
MATTHEWWITHANM
MATTHEW DAPENA-TRETTER
[email protected] HZDG