Redux Universal

25
Redux Universal by Sebastian Siemssen & Nik Graf

Transcript of Redux Universal

Page 1: Redux Universal

Redux Universalby Sebastian Siemssen & Nik Graf

Page 2: Redux Universal

Redux Universal @nikgraf

Nik Graf@nikgraf

[email protected]

Creator of Belle

Working with StarterSquad

Page 3: Redux Universal

History

Page 4: Redux Universal

Redux Universal @nikgraf

Server side rendering• (Client) Request the website's HTML

• (Server) Execute the Code

• (Server) Collect the data

• (Server) Render the page in the backend

• (Server) Serve the page with content

• (Client) -> Render the content

Page 5: Redux Universal

Redux Universal @nikgraf

?

Page 6: Redux Universal

Universal Rendering

Page 7: Redux Universal

Redux Universal @nikgraf

Benefits

• Search Engine Indexability

• Code Reusability & Maintainability

• Faster Perceived Load Time !?

Page 8: Redux Universal

Redux Universal @nikgraf

Client side rendering• (Client) Request the website's HTML

• (Server) Serve the page without content

• (Client) Request JavaScript code based on sources in the HTML

• (Server) Serve the JavaScript code

• (Client) Load & execute JavaScript

• (Client) -> Render a loading page

• (Client) Request data based on the executed code

• (Server) Collect and serve the data

• (Client) -> Render the content

Page 9: Redux Universal

Redux Universal @nikgraf

Isomorphic Universal rendering• (Client) Request the website's HTML

• (Server) Execute the JavaScript Code

• (Server) Collect the data

• (Server) Render the page in the backend

• (Server) Serve the page with content

• (Client) -> Render the content

• (Client) Request JavaScript code based on sources in the HTML

• (Server) Serve the JavaScript code

• (Client) Load & execute JavaScript

Page 10: Redux Universal

Redux Universal @nikgraf

Render on the Server (React)

import React, { Component } from 'react';import { renderToString } from 'react-dom/server';

class MyComponent extends Component { render() { return <div>Hello World</div>; }}

const html = renderToString(MyComponent);

Page 11: Redux Universal

Redux Universal @nikgraf

Render on the Server (React/Redux)

import { renderToString } from 'react-dom/server';import { createStore } from 'redux';import { Provider } from 'react-redux';import rootReducer from '../reducers';import App from '../components/App';

const store = createStore(rootReducer);const html = renderToString( <Provider store={store}> <App/> </Provider>);

Page 12: Redux Universal

Redux Universal @nikgraf

Redux on the Server I/IIIimport ReactDOM from 'react-dom';import { createStore } from 'redux';import { Provider } from 'react-redux';import rootReducer from '../reducers';import App from '../components/App';

const initialState = window.__INITIAL_STATE__;const store = createStore(rootReducer, initialState);

const rootElement = document.getElementById('app');

ReactDOM.render( <Provider store={store}><App/></Provider>, rootElement);

Page 13: Redux Universal

Redux Universal @nikgraf

Redux on the Server II/IIIconst renderFullPage = (html, initialState) => { return ` <!doctype html> <html> <body> <div id="app">${html}</div> <script> window.__INITIAL_STATE__ = ${JSON.stringify(initialState)}; </script> <script src="/static/bundle.js"></script> </body> </html> `;}

Page 14: Redux Universal

Redux Universal @nikgraf

Redux on the Server III/III

app.use((request, response) => { const store = createStore(rootReducer); const html = renderToString( <Provider store={store}> <App/> </Provider> ); const state = store.getState(); response.send(renderFullPage(html, state));});

Page 15: Redux Universal

Redux Universal @nikgraf

What about async actions?

Page 16: Redux Universal

Redux Universal @nikgraf

Async Action Exampleimport fetch from 'isomorphic-fetch';

export function fetchFriends() { return dispatch => { dispatch({ type: 'FETCH_FRIENDS' }); return fetch('http://localhost/api/friends/') .then(response => response.json()) .then(json => { dispatch({ type: 'RECEIVE_FRIENDS', payload: json }); }); };}

Page 17: Redux Universal

Redux Universal @nikgraf

Issue with Async

Async ActionRender

RenderAsync Action

Page 18: Redux Universal

Redux Universal @nikgraf

Before using redux-universalimport { createStore, applyMiddleware } from 'redux';import thunk from 'redux-thunk';import rootReducer from '../reducers';

const createStoreWithMiddleware = applyMiddleware( thunk)(createStore);

export default function configureStore(initialState) { return createStoreWithMiddleware(rootReducer, initialState);}

Page 19: Redux Universal

Redux Universal @nikgraf

Using redux-universalimport { createStore } from 'redux';import thunk from 'redux-thunk';import rootReducer from '../reducers';

const applyMiddleware = __SERVER__ ? require('redux-universal') : require('redux').applyMiddleware;

const createStoreWithMiddleware = applyMiddleware( thunk)(createStore);

export default function configureStore(initialState) { return createStoreWithMiddleware(rootReducer, initialState);}

Page 20: Redux Universal

Redux Universal @nikgraf

Before using redux-universal

const html = renderToString( <Provider store={store}> <App/> </Provider>);const state = store.getState();res.send(renderFullPage(html, state));

Page 21: Redux Universal

Redux Universal @nikgraf

Using redux-universalstore.renderUniversal( renderToString, <Provider store={store}> <App/> </Provider> ) .then(({ output }) => { const state = store.getState(); response.send(renderFullPage(output, state)); }) .catch(({ output, error }) => { console.warn(error.message); });

Page 22: Redux Universal

Redux Universal @nikgraf

How it works

-> render

-> wait for promise

-> render

-> resolve

Page 23: Redux Universal

Redux Universal @nikgraf

How it works-> render

-> wait for promiseA

-> render

-> wait for promiseB

-> render

-> resolve

Page 24: Redux Universal
Page 25: Redux Universal

Redux Universal @nikgraf

Fin

Checkout Redux Universal

https://github.com/reducks/redux-universal