React Server Side Rendering
A Software Presentation From
Jeremy Zerr
Site: [Link]
[Link]
[Link]
The Plan
Start with a React project started from Create React App
that has some API calls, defines title tag, and a couple
routes
Show what problem we are trying to solve and how we
would like to solve it
Evolve the app into a React Server Side Rendering,
showing the challenges encountered along the way
The App
The App - Title tags
The App - API Calls
/heroes
/heroes/0
The App - Code
Zerrtech/zerrtech-react-ssr-demo
4 branches, 1 for each iteration
step-1-normal-app
step-2-ssr-initial
step-3-ssr-server-seed
step-4-ssr-api
1
Initial App Demo
Branch: step-1-normal-app
Initial page load has nothing!
Page fetches heroes from
API then renders
1
Initial App Demo
Empty HTML
This empty initial page load is by design.
It’s a Single Page App (SPA) after all.
React renders into the div id=“root”
1
What’s wrong with that?
Google can crawl Javascript on a page, but it takes extra steps
and can delay full indexing since they have to wait for rendering
by doing two passes.
Performance wise, one trip to the server is quicker than N trips to
the server to generate a page, especially in mobile where #
parallel requests is smaller and connections are slower.
Combined with SSR caching, this can mean that each page is
only rendered once and used by many users. Loading indicators
added while waiting for API calls wouldn’t really show up, better
user experience.
1
Rendering HTML
only page
Image from SEOpressor
Rendering JS
page
Image from SEOpressor
1
Google uses Chrome 41 to
crawl
I have version 71
Can I Use - 41 vs. 71
Use the Google Search
Console to Fetch as Google
(or new Search Console
URL Inspection)
Google Search Rendering Guide
1
Why don’t all sites
do SSR then?
It’s good for content-heavy, largely publicly accessible apps.
If most of your content is behind a login, then SSR can’t get
at it either.
A proper SSR implementation would use a layer of caching,
so if you have data that absolutely needs to be as up to date
as possible, probably not a good fit.
Requires redesigning data fetching within components,
ideal solution is specific to your app, no generic solution
Wait!!!
Weren’t all sites
like this in 1999?
1
How does React rendering
normally work?
A user types your home page URL into the browser
Browser sends a request to the server for your home page
HTML for home page is returned to Browser, but has a
blank content body and links to scripts/CSS
React boots up in Browser, renders the home page
Browser React component may fire off API requests that
when they return, causes another React render
1
How does React SSR work?
A user types your home page URL into the browser
Browser sends a request to the server for your home page
Server fetches data needed for the home page, seeds your component
state, renders your React components, gets the HTML created by them,
stuffs it into your React root in [Link] and returns it to the browser
React boots up in Browser, realizes everything was already rendered
so has no changes (virtual DOM)
Browser React component does not need to fire off API calls because
they were already done on the server
2
Initial SSR
Branch: step-2-ssr-initial
Initial page load has
our loading indicator
Client fetches heroes from
API then renders
2
Initial SSR
Code changes
Added a server script
Babel compiled
Express
React DOM Server renderToString and StaticRouter
Build prod with yarn build, then start SSR with yarn start:ssr
Code diff - step 1 vs step 2
Static files served
out of build dir
We load our Routes
under StaticRouter
instead of BrowserRouter
We grab our [Link]
and stuff our HTML in
Step 2 - [Link]
2
Initial SSR
Review
Notice no API calls were done within SSR
The render is synchronous, makes one pass through then
returns what it has
Fact: when doing SSR, componentDidMount is not called
We need to do our API calls on the server, then seed our
state within our component so SSR can do the full page
3
SSR Server Seed
Branch: step-3-ssr-server-seed
Data all there!
Title tag, check!
3
SSR Server Seed
Code changes
Added fetching data into the server script by using a
static method on each route component
Pass the data into the component using StaticRouter
context param
Render Helmet and replace in HTML
Code diff - step 2 vs step 3
3
SSR Server Seed
Data fetching
Static method called
getInitialState() added
into Route component.
Static so it can be called
on the server easily.
Server looks for a
matching route and a
getInitialState method, if
so calls it
3
SSR Server Seed
Data fetching
We wait for API calls to
be done then add data to
context passed into
StaticRouter
Back in the Route
component, we look for
that data and merge into
state in the constructor.
staticContext is provided
by React router
withRouter()
3
SSR Server Seed
Review
OK great, but now we
are wasting our API
call on the frontend,
how do we prevent
that?
We’ll put that same
initialState in our
[Link] so on the
client side, we can
also seed that data
and avoid the API call
4
SSR API
Branch: step-4-api
Data all there! No extra API call
Title tag, check!
4
SSR API
Code changes
Add a placeholder in [Link] we can stuff our initial
state into
Check for this existing data in our static getInitialState()
method
Delete the data after we use it so other pages don’t use
it
Code diff - step 3 vs step 4
4
SSR API
API call saving
Add a variable in
[Link]
Server will stuff
initialState into that
var
HeroList
getInitialState
checks for existing
data
React SSR Summary
Demo of React SSR from create react app without
ejecting webpack config
Showed how to use SSR on an app that has async API
calls and dynamic title tags
Implemented where SSR is used and we also eliminate
the client side API calls for max efficiency
As good as 1999? Definitely!
Next Steps
Great opportunity to build a generic SSR React component
for Route components to inherit from
Encapsulates all that window and staticContext stuff
to make it easy on devs.
Put caching in front of SSR so that you aren’t running SSR
on the page every time
React Suspense API has high hopes to make it easier to
identify those async API calls and make SSR easier
Thanks! Connect with us!
We would love to build your next app
A Software Presentation From
Jeremy Zerr
Site: [Link]
[Link]
[Link]