Slide 1

Slide 1 text

ISOMORPHIC JS, SERVER-SIDE RENDERING, REACT & ROCKEFELLER

Slide 2

Slide 2 text

• Matthew Dapena-Tretter • matthewwithanm • JavaScript → AS3 →
 Python → JavaScript

Slide 3

Slide 3 text

• 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

Slide 10

Slide 10 text

JS

Slide 11

Slide 11 text

hzdg.com JS

Slide 12

Slide 12 text

hzdg.com JS Welcome | HZDG

Slide 13

Slide 13 text

hzdg.com JS Welcome | HZDG

Slide 14

Slide 14 text

hzdg.com JS JS Welcome | HZDG

Slide 15

Slide 15 text

hzdg.com JS hzdg.com/contact Contact | HZDG <meta name=“description” <meta name=“keywords” </head> <body> JS <html> <head> <title>Welcome | HZDG

Slide 16

Slide 16 text

hzdg.com JS hzdg.com/contact Contact | HZDG <meta name=“description” <meta name=“keywords” </head> <body> JS <html> <head> <title>Welcome | HZDG

Slide 17

Slide 17 text

Welcome | HZDG
hzdg.com g JS

Slide 18

Slide 18 text

Welcome | HZDG
hzdg.com hzdg.com/contact Contact | HZDG
g JS

Slide 19

Slide 19 text

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?

Slide 36

Slide 36 text

SOURCES OF IMPURITY • Randomness • Temporal values • “3 hours ago” • Date.now() • Stateful external resources (API) • Non-deterministic native APIs • Object iteration • JSON.stringify() • Engine differences

Slide 37

Slide 37 text

No content

Slide 38

Slide 38 text

• 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