Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com...

78
<title>Server Side Rendering with React and Redux</title> <p>Presented by Fiax</p> <p>Date: 2020-08-20</p>

Transcript of Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com...

Page 1: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

<title>Server Side Rendering with React and Redux</title>

<p>Presented by Fiax</p>

<p>Date: 2020-08-20</p>

Page 2: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

Introduction

<h3>Introduction</h3>

<ul>

<li>Traditional Single Page Application (SPA) flow in React</li>

<li>Server Side Rendering (SSR) challenges</li>

<li>SSR concepts graphics and diagrams</li>

<li>Analize snapshot codes</li>

</ul>

Page 3: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

Technologies

<p>Technologies</p>

Page 4: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

Technologies

<p>Technologies</p>

Page 5: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

Technologies

<p>Technologies</p>

Page 6: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

<h2>Why Server Side Rendering (SSR) is needed?</h2>

Why SSR?

Page 7: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

<h1>Javascript </h1>

Single Page Application

<pre>Browsers are more powerful. We started to create entire

websites and web apps with client-side JavaScript. We started to call

this "Single Page Application" (SPA).</pre>

Page 8: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

Single Page Application

Browser Server

User navigates to spa.com Receives request

Sends back index.htmlIndex.html

Page 9: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

Single Page Application

User navigates to spa.com Receives request

Sends back index.html<!DOCTYPE html>

<html>

<head>

<title>SPA</title>

</head>

<body>

<div id="root"></div>

<script src="bundle.js"></script>

</body>

</html>

Browser Server

Page 10: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

Single Page Application

User navigates to spa.com Receives request

Sends back index.html<!DOCTYPE html>

<html>

<head>

<title>SPA</title>

</head>

<body>

<div id="root"></div>

<script src="bundle.js"></script>

</body>

</html>

Browser Server

No content

Page 11: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

Single Page Application

User navigates to spa.com Receives request

Sends back index.html<!DOCTYPE html>

<html>

<head>

<title>SPA</title>

</head>

<body>

<div id="root"></div>

<script src="bundle.js"></script>

</body>

</html>

Browser Server

Page 12: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

Single Page Application

User navigates to spa.com Receives request

Sends back index.html<!DOCTYPE html>

<html>

<head>

<title>SPA</title>

</head>

<body>

<div id="root"></div>

<script src="bundle.js"></script>

</body>

</html>

Browser Server

Page 13: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

Single Page Application

Browser Server

User navigates to spa.com Receives request

Sends back index.htmlIndex.html

Page 14: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

Single Page Application

User navigates to spa.com Receives request

Sends back index.htmlIndex.html

Requests bundle.js Receives request

Browser Server

Page 15: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

Single Page Application

User navigates to spa.com Receives request

Sends back index.htmlIndex.html

Requests bundle.js Receives request

Sends back bundle.jsReact app

Browser Server

Page 16: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

Single Page Application

User navigates to spa.com Receives request

Sends back index.htmlIndex.html

Requests bundle.js Receives request

Sends back bundle.js

Receives request

React app

Requests for data

Browser Server

Page 17: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

Single Page Application

User navigates to spa.com Receives request

Sends back index.htmlIndex.html

Requests bundle.js Receives request

Sends back bundle.js

Receives request

Sends back JSON data

React app

Requests for data

App renders

Browser Server

Page 18: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

Single Page Application

User navigates to spa.com Receives request

Sends back index.htmlIndex.html

Requests bundle.js Receives request

Sends back bundle.js

Receives request

Sends back JSON data

React app

Requests for data

App renders

Browser Server

Page 19: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

Single Page Application

User navigates to spa.com Receives request

Sends back index.htmlIndex.html

Requests bundle.js Receives request

Sends back bundle.js

Receives request

Sends back JSON data

React app

Requests for data

App renders

Browser Server

Page 20: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

Single Page Application

Requests page

Requests JS file

Content visible

Browser Time

Page 21: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

<h2>Why SSR is needed?</h2>

Why SSR?

Page 22: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

Server Side Rendering

User navigates to spa.com Receives request

Sends back index.htmlIndex.html

Requests bundle.js Receives request

Sends back bundle.js

Receives request

Sends back JSON data

React app

Requests for data

App renders

Browser Server

Page 23: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

User navigates to spa.com Receives request

Sends back index.htmlIndex.html

Requests bundle.js Receives request

Sends back bundle.js

Receives request

Sends back JSON data

React app

Requests for data

App renders

Browser Server

Server Side Rendering

Page 24: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

User navigates to spa.com Receives request

Sends back index.htmlIndex.html

Browser Server

Server Side Rendering

Page 25: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

User navigates to spa.com Receives request

Sends back index.htmlIndex.html

Browser Server

Fetches any required data

Renders

Generates HTML

Loads up in memory

Server Side Rendering

Page 26: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

User navigates to spa.com Receives request

Sends back index.html

Browser Server

Fetches any required data

Renders

Generates HTML

Loads up in memory<!DOCTYPE html>

<html>

<head>

<title>SSR</title>

</head>

<body>

<div id="root"></div>

<h3>I came from the server

</h3>

<script src="bundle.js">

</script>

</body>

</html>

Server Side Rendering

Page 27: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

Requests page

Content visible

Browser Time

Server Side Rendering

Page 28: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

Server Side Rendering

SSR + SPA

Page 29: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

Server Side Rendering

SSR + SPA =

Page 30: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

Server Side Rendering

SSR + SPA = Universal App

Page 31: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

<h3>Benefits from SSR</h3>

Server Side Rendering

<ul>

<li>Faster times for the initial page render</li>

<li>Fully indexable HTML pages</li>

</ul>

Page 32: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

<h3>Challenges on SSR</h3>

SSR with React and Redux

<ul>

<li>JSX on the server</li>

<li>Need to turn components into HTML</li>

<li>Need state rehydration on the browser</li>

<li>Redux needs different configuration on browser vs server</li>

<li>Routing on the server</li>

<li>Need to detect when all initial data load are completed on server</li>

</ul>

Page 33: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

// All imports required in server.js file

const app = express()

app.get('*', (request, response) => {const content = renderToString(<App />)

res.send(content)})

app.listen(port, () => {console.log(`Server listening to port ${port} on ${host}`)

})

<h3>JSX on the server</h3>

SSR with React and Redux

Page 34: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

// All imports required in server.js file

const app = express()

app.get('*', (request, response) => {const content = renderToString(<App />)

res.send(content)})

app.listen(port, () => {console.log(`Server listening to port ${port} on ${host}`)

})

<h3>JSX on the server</h3>

SSR with React and Redux

Page 35: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

// All imports required in server.js file

const app = express()

app.get('*', (request, response) => {const content = renderToString(<App />)

res.send(content)})

app.listen(port, () => {console.log(`Server listening to port ${port} on ${host}`)

})

<h3>JSX on the server</h3>

SSR with React and Redux

Page 36: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

// All imports required in server.js file

const app = express()

app.get('*', (request, response) => {const content = renderToString(<App />)

res.send(content)})

app.listen(port, () => {console.log(`Server listening to port ${port} on ${host}`)

})

<h3>JSX on the server</h3>

SSR with React and Redux

Page 37: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

// All imports required in server.js file

const app = express()

app.get('*', (request, response) => {const content = renderToString(<App />)

res.send(content)})

app.listen(port, () => {console.log(`Server listening to port ${port} on ${host}`)

})

<h3>JSX on the server</h3>

SSR with React and Redux

$ node server.js

Page 38: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

// All imports required in server.js file

const app = express()

app.get('*', (request, response) => {const content = renderToString(<App />)

res.send(content)})

app.listen(port, () => {console.log(`Server listening to port ${port} on ${host}`)

})

<h3>JSX on the server</h3>

$ node server.jsSyntax Error: Unexpected token

SSR with React and Redux

Page 39: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

// All imports required in server.js file

const app = express()

app.get('*', (request, response) => {const content = renderToString(<App />)

res.send(content)})

app.listen(port, () => {console.log(`Server listening to port ${port} on ${host}`)

})

<h3>JSX on the server</h3>

SSR with React and Redux

Page 40: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

// All imports required in server.js fileimport { renderToString } from 'react-dom/server'

const app = express()

app.get('*', (request, response) => {const content = renderToString(<App />)const html = `<html>

<head></head><body>

<div id="root">${content}</div><script src="bundle.js"></script>

</body></html>`

res.send(html )})

<h3>JSX on the server</h3>

SSR with React and Redux

<i>Challenge: Need to turn components into HTML</i>

Page 41: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

// All imports required in server.js file

const app = express()

app.get('*', (request, response) => {const content = renderToString(<App />)

res.send(content)})

app.listen(port, () => {console.log(`Server listening to port ${port} on ${host}`)

})

<h3>JSX on the server</h3>

SSR with React and Redux

Page 42: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

SSR with React and Redux

Page 43: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

// webpack.base.js file

module.exports = {

module: {rules: [{

test: /\.js?$/,loader: 'babel-loader',exclude: /node_modules/,options: {

presets: ['react','stage-0',['env', { targets: { browsers: ['last 2 versions'] } }]

]}

}]}

}

SSR with React and Redux

Page 44: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

// webpack.client.js file

const path = require('path')const merge = require('webpack-merge')const baseConfig = require('./webpack.base.js')

const config = {

entry: './src/client/client.js',

output: {filename: 'bundle.js',path: path.resolve(__dirname, 'public')

}}

module.exports = merge(baseConfig, config)

SSR with React and Redux

Page 45: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

// webpack.server.js file

const path = require('path')const merge = require('webpack-merge')const baseConfig = require('./webpack.base.js')

const config = {target: 'node',entry: './src/client/client.js', entry: './src/server.js',

output: {filename: 'bundle.js',path: path.resolve(__dirname, 'public') path: path.resolve(__dirname, 'build')

}}

module.exports = merge(baseConfig, config)

SSR with React and Redux

Page 46: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

// All imports required in server.js file

const app = express()

app.get('*', (request, response) => {const content = renderToString(<App />)

res.send(content)})

app.listen(port, () => {console.log(`Server listening to port ${port} on ${host}`)

})

<h3>JSX on the server</h3>

$ node bundle.js

SSR with React and Redux

Page 47: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

// All imports required in server.js file

const app = express()

app.get('*', (request, response) => {const content = renderToString(<App />)

res.send(content)})

app.listen(port, () => {console.log(`Server listening to port ${port} on ${host}`)

})

<h3>Routing</h3>

$ node bundle.js

SSR with React and Redux

Page 48: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

<h3>Router</h3>

Request to /

Request to /path

Browser request

*

Express Route Handler

/path

/

React Router

SSR with React and Redux

Page 49: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

<h3>Router</h3>

BrowserRouter

Client Server

StaticRouter

SSR with React and Redux

Page 50: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

<h3>Router</h3>

import { renderRoutes } from 'react-router-config'import { BrowserRouter} from 'react-router-dom'

ReactDOM.hydrate(<Provider store={store}>

<BrowserRouter>{renderRoutes(Routes)}

</BrowserRouter></Provider>,document.querySelector('#root')

)

import { renderRoutes } from 'react-router-config'import { StaticRouter } from 'react-router-dom'

export default (request, store) => {const content = renderToString(<Provider store={store}>

<StaticRouter location={request.url}>{renderRoutes(Routes)}

</StaticRouter></Provider>

)}

Client Server

SSR with React and Redux

Page 51: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

<h3>Router</h3>

import { renderRoutes } from 'react-router-config'import { BrowserRouter} from 'react-router-dom'

ReactDOM.hydrate(<Provider store={store}>

<BrowserRouter>{renderRoutes(Routes)}

</BrowserRouter></Provider>,document.querySelector('#root')

)

import { renderRoutes } from 'react-router-config'import { StaticRouter } from 'react-router-dom'

export default (request, store) => {const content = renderToString(<Provider store={store}>

<StaticRouter location={request.url}>{renderRoutes(Routes)}

</StaticRouter></Provider>

)}

Client Server

SSR with React and Redux

Page 52: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

<h3>Router</h3>

import { renderRoutes } from 'react-router-config'import { BrowserRouter} from 'react-router-dom'

ReactDOM.hydrate(<Provider store={store}>

<BrowserRouter>{renderRoutes(Routes)}

</BrowserRouter></Provider>,document.querySelector('#root')

)

import { renderRoutes } from 'react-router-config'import { StaticRouter } from 'react-router-dom'

export default (request, store) => {const content = renderToString(<Provider store={store}>

<StaticRouter location={request.url}>{renderRoutes(Routes)}

</StaticRouter></Provider>

)}

Client Server

SSR with React and Redux

Page 53: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

<h3>Routes</h3>

// Routes.js

export default [{component: App,loadData: ({ dispatch }) => dispatch(fetchData()),routes: [

{component: Home,path: '/',exact: true

},{

component: _Component,path: '/path'

}]

}]

SSR with React and Redux

Page 54: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

<h3>Routes</h3>

// Routes.js

export default [{component: App,loadData: ({ dispatch }) => dispatch(fetchData()),routes: [

{component: Home,path: '/',exact: true

},{

component: _Component,path: '/path'

}]

}]

SSR with React and Redux

Page 55: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

<h3>Routes</h3>

// Routes.js

export default [{component: App,loadData: ({ dispatch }) => dispatch(fetchData()),routes: [

{component: Home,path: '/',exact: true

},{

component: _Component,path: '/path'

}]

}]

SSR with React and Redux

Page 56: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

Figure out what components would have rendered (based on URL)

Server Time

Call 'loadData' function attached to

each of those components

Detect all requests are completed

Render the app with the collected data

Send result to browser

SSR with React and Redux

Page 57: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

/* … */

const promises = matchRoutes(Routes, request.url).map(({ route }) => {

return route.loadData ? route.loadData(store) : null}).map(promise => {

if (promise) {return new Promise((resolve, reject) => {promise.then(resolve).catch(resolve)})

}})

Promise.all(promises).then(() => {const reduxState = store.getState( )const html= htmlTemplate(request, reduxState )

res.send(html)})

SSR with React and Redux

Page 58: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

/* … */

const promises = matchRoutes(Routes, request.url).map(({ route }) => {

return route.loadData ? route.loadData(store) : null}).map(promise => {

if (promise) {return new Promise((resolve, reject) => {promise.then(resolve).catch(resolve)})

}})

Promise.all(promises).then(() => {const reduxState = store.getState( )const html= htmlTemplate(request, reduxState )

res.send(html)})

SSR with React and Redux

// Routes.js

export default [{component: App,loadData: ({ dispatch }) => dispatch(fetchData()),routes: [

{component: Home,path: '/',exact: true

},{

component: _Component,path: '/path'

}]

}]

Page 59: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

/* … */

const promises = matchRoutes(Routes, request.url).map(({ route }) => {

return route.loadData ? route.loadData(store) : null}).map(promise => {

if (promise) {return new Promise((resolve, reject) => {promise.then(resolve).catch(resolve)})

}})

Promise.all(promises).then(() => {const reduxState = store.getState( )const html= htmlTemplate(request, reduxState )

res.send(html)})

SSR with React and Redux

// Routes.js

export default [{component: App,loadData: ({ dispatch }) => dispatch(fetchData()),routes: [

{component: Home,path: '/',exact: true

},{

component: _Component,path: '/path'

}]

}]

Page 60: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

/* … */

const promises = matchRoutes(Routes, request.url).map(({ route }) => {

return route.loadData ? route.loadData(store) : null}).map(promise => {

if (promise) {return new Promise((resolve, reject) => {promise.then(resolve).catch(resolve)})

}})

Promise.all(promises).then(() => {const reduxState = store.getState( )const html= htmlTemplate(request, reduxState )

res.send(html)})

Promise.all

promise promise promise

SSR with React and Redux

Page 61: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

/* … */

const promises = matchRoutes(Routes, request.url).map(({ route }) => {

return route.loadData ? route.loadData(store) : null}).map(promise => {

if (promise) {return new Promise((resolve, reject) => {promise.then(resolve).catch(resolve)})

}})

Promise.all(promises).then(() => {const reduxState = store.getState( )const html= htmlTemplate(request, reduxState )

res.send(html)})

Promise.all

promise promise promise

SSR with React and Redux

Page 62: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

/* … */

const promises = matchRoutes(Routes, request.url).map(({ route }) => {

return route.loadData ? route.loadData(store) : null}).map(promise => {

if (promise) {return new Promise((resolve, reject) => {promise.then(resolve).catch(resolve)})

}})

Promise.all(promises).then(() => {const reduxState = store.getState( )const html= htmlTemplate(request, reduxState )

res.send(html)})

Promise.all

promise promise promise

unresolved rejected resolved

Call .catch function

SSR with React and Redux

Page 63: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

/* … */

const promises = matchRoutes(Routes, request.url).map(({ route }) => {

return route.loadData ? route.loadData(store) : null}).map(promise => {

if (promise) {return new Promise((resolve, reject) => {promise.then(resolve).catch(resolve)})

}})

Promise.all(promises).then(() => {const reduxState = store.getState( )const html= htmlTemplate(request, reduxState )

res.send(html)})

Promise.all

promise promise promise

Call .then function

SSR with React and Redux

Page 64: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

/* … */

const promises = matchRoutes(Routes, request.url).map(({ route }) => {

return route.loadData ? route.loadData(store) : null}).map(promise => {

if (promise) {return new Promise((resolve, reject) => {promise.then(resolve).catch(resolve)})

}})

Promise.all(promises).then(() => {const reduxState = store.getState( )const html= htmlTemplate(request, reduxState )

res.send(html)})

SSR with React and Redux

Figure out what components would have rendered (based on URL)

Server

Call 'loadData' function attached to

each of those components

Detect all requests are completed

Render the app with the collected data

Send result to browser

Page 65: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

/* … */

const promises = matchRoutes(Routes, request.url).map(({ route }) => {

return route.loadData ? route.loadData(store) : null}).map(promise => {

if (promise) {return new Promise((resolve, reject) => {promise.then(resolve).catch(resolve)})

}})

Promise.all(promises).then(() => {const reduxState = store.getState( )const html= htmlTemplate(request, reduxState )

res.send(html)})

SSR with React and Redux

Page 66: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

<h3>Redux principles</h3>

<ul>

<li>Single source of truth</li>

<li>State is read-only</li>

<li>Changes are made with pure functions</li>

</ul>

SSR with React and Redux

Page 67: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

/* … */

const content = renderToString(<Provider store={store}>

<StaticRouter location={request.url}>{renderRoutes(Routes)}

</StaticRouter></Provider>

)

const html = `<html><head></head><body>

<div id="root">${content}</div><script>

window.INITIAL_STATE = ${JSON.stringify(store.getState())}</script><script src="bundle.js"></script>

</body></html>`

SSR with React and Redux

Page 68: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

/* … */

const content = renderToString(<Provider store={store}>

<StaticRouter location={request.url}>{renderRoutes(Routes)}

</StaticRouter></Provider>

)

const html = `<html><head></head><body>

<div id="root">${content}</div><script>

window.INITIAL_STATE = ${JSON.stringify(store.getState())}</script><script src="bundle.js"></script>

</body></html>`

SSR with React and Redux

Page 69: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

/* … */

const content = renderToString(<Provider store={store}>

<StaticRouter location={request.url}>{renderRoutes(Routes)}

</StaticRouter></Provider>

)

const html = `<html><head></head><body>

<div id="root">${content}</div><script>

window.INITIAL_STATE = ${JSON.stringify(store.getState())}</script><script src="bundle.js"></script>

</body></html>`

const initialState = window.INITIAL_STATE ? window.INITIAL_STATE : {}const store = createStore(reducers, initialState)

ReactDOM.hydrate(<Provider store={store}><BrowserRouter>

{renderRoutes(Routes)}</BrowserRouter>

</Provider>, document.querySelector('#root'))

Client

SSR with React and Redux

Page 70: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

/* … */

const content = renderToString(<Provider store={store}>

<StaticRouter location={request.url}>{renderRoutes(Routes)}

</StaticRouter></Provider>

)

const html = `<html><head></head><body>

<div id="root">${content}</div><script>

window.INITIAL_STATE = ${JSON.stringify(store.getState())}</script><script src="bundle.js"></script>

</body></html>`

const initialState = window.INITIAL_STATE ? window.INITIAL_STATE : {}const store = createStore(reducers, initialState)

ReactDOM.hydrate(<Provider store={store}><BrowserRouter>

{renderRoutes(Routes)}</BrowserRouter>

</Provider>, document.querySelector('#root'))

Client

SSR with React and Redux

<i>Challenge: Need state rehydration on the browser</i>

Page 71: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

<h3>Search Engine Optimization (SEO)</h3>

<ul>

<li>Helps people to find your website using search engines</li>

<li>Brings more online business by improving search engine ranking</li>

</ul>

SSR with React and Redux

Page 72: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

/* … */

const html = `<html><head></head><body>

<div id="root">${content}</div><script>

window.INITIAL_STATE = ${JSON.stringify(store.getState())}</script><script src="bundle.js"></script>

</body></html>`

SSR with React and Redux

Page 73: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

import { Helmet } from 'react-helmet'

const helmet = Helmet.renderStatic()

const html = `<html><head>${helmet.title.toString()}${helmet.meta.toString()}</head><body>

<div id="root">${content}</div><script>

window.INITIAL_STATE = ${JSON.stringify(store.getState())}</script><script src="bundle.js"></script>

</body></html>`

SSR with React and Redux

Page 74: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

import { Helmet } from 'react-helmet'

const helmet = Helmet.renderStatic()

const html = `<html><head>${helmet.title.toString()}${helmet.meta.toString()}</head><body>

<div id="root">${content}</div><script>

window.INITIAL_STATE = ${JSON.stringify(store.getState())}</script><script src="bundle.js"></script>

</body></html>`

SSR with React and Redux

Page 75: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

import serialize from 'serialize-javascript'

const helmet = Helmet.renderStatic()

const html = `<html><head>${helmet.title.toString()}${helmet.meta.toString()}</head><body>

<div id="root">${content}</div><script>

window.INITIAL_STATE = ${serialize(store.getState())}</script><script src="bundle.js"></script>

</body></html>`

SSR with React and Redux

Page 76: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

<h3>More Challenges</h3>

<ul>

<li>Authentication in SSR</li>

<li>Error Handling and Redirects</li>

</ul>

SSR with React and Redux

Page 77: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

<p>Presented by Fiax</p>

<p>Date: 2020-08-20</p>

<title>SSR with React and Redux</title>

Page 78: Server Side Rendering with React and Redux · Single Page Application User navigates to spa.com Receives request Index.html Sends back index.html Requests bundle.js Receives request

<p>Presented by Fiax</p>

<p>Date: 2020-08-20</p>

<title>SSR with React and Redux</title>