Workshop Isomorphic Web Apps with ReactJS:
- Universal web apps - Isomorphic
- Server Side Rendering (SSR) with ReactJS
- Server Side Rendering with Redux
- Server Side Rendering with React Router
- Server Side Rendering: server.js - Main Entry Point
- Server Side Rendering: server.js - HTML Template
- Client main entry point: client.js
- Webpack bundles
- Avoiding FOUC - Webpack ExtractTextPlugin
- Webpack code splitting
- React Router - Configuration with Plain Routes
- React Router - Dynamic Routing & WebPack
- Dynamic Routing with new Reducers
- Combining new Reducers - ReducerRegistry
- Data fetching before rendering
- React Router + Redux + Redial: Server Side
- React Router + Redux + Redial: provideHooks
- React Router + Redux + Redial: Client Side
- SEO friendly universal web apps - React-Helmet
- React-Helmet - Server Side Rendering
Presentado por ingeniero: Marc Torrent
3. Universal web apps - Isomorphic
Web Application
Code (JS)
Server - Routing and Data
gathering (Rest API)
ClientBrowser
HTTP Request,
a new Page
With the data,
inject it to our
application code
render() and obtain
valid HTML
HTTP Response with HTML, Web
Application Code and JSON Data
Web Application
Code (JS)
Request Data, AJAX or
Web sockets â JSON Routing
Isomorphic: the Client and the Server share the
same code for routing, data gathering and
rendering.
4. HTML Page
Server Side Rendering (SSR) with ReactJS
react-dom/server renderToString(ReactElement)
<MyReactComponent {...props} />
HTML + ReactJS
Virtual DOM IDâsReactDOM.render(App(window.APP_PROPS),
document.getElementById('content')
No re-rendering as thereâs no difference in Virtual DOM !!!
5. Server Side Rendering with Redux
react-dom/server const htmlEl = renderToString(ReactElement)
const store = createStore(reducers);
<Provider store={store}>
<MyReactComponent {...props} />
</ Provider>
No re-rendering as thereâs no difference in Virtual DOM !!!
const initialState = store.getState();
const html = `
<HTML> <body>
<script>window.initialState =
JSON.Stringify(initialState);</script>
<div>${htmlEl}</div>
</body></HTML>`;
res.send(html);
Client.jsx
const initialState = window.initialState;
const store = createStore(reducers,
initialState);
<Provider store={store}>
<MyReactComponent {...props} />
</ Provider>
6. Server Side Rendering with React Router
import { createMemoryHistory, RouterContext, match } from 'react-router';
Finds the route from the current
location and returns the
component to be rendered.
Creates a Location object
from the current url to be
used by the match function.
Renders the component
tree for a given router
state.
import { createMemoryHistory, RouterContext, match } from 'react-router';
const history = createMemoryHistory(req.path);
match({ routes, history }, (err, redirectLocation, renderProps) => {
âŠ
const InitialComponent = (<RouterContext {...renderProps} />);
âŠ
const componentHTML = renderToString(InitialComponent);
...
15. Dynamic Routing with new Reducers
At initialization we combine reducers to build the store...
const rootReducer = combineReducers({authReducer, otherReducer});
const store = createStore(rootReduer, initialState,
applyMiddleware(...middleware);
âŠ
<Provider store={store}>
<Router routes={routes} />
</Proider>
âŠ
But what happens if we load a route containing a new
reducer that is needed for the components of that new
route???
16. Combining new Reducers - ReducerRegistry
{
path: âfaqâ,
getComponents:(location, cb) {
require.ensure([â./components/FAQâ, â./reducerâ], require => {
const FAQ = require(â./components/FAQâ).default;
const faqReducer = require(â./reducerâ).default;
store.replaceReducer(combineReducers({...existingRedu
cers, faqReducer}));
cb(null, FAQ);
});
}
}
Now we have the initial reducers combined with the new
ones and applied to the store via store.replaceReducer
17. Data fetching before rendering
We need data to be accessible to Route Components before rendering those
components.
In SSR itâs not possible to fetch data in componentWillMount or
componentDidMount:
1. componentDidMount is not available on server rendering.
2. componentWillMount is called immediately before rendering and changes
in state wonât trigger a re-rendering â fetching data here doesnât ensures
that the render method will have all the data that is needed.
ReactRouter â onEnter = Function to be called before
rendering a Routeâs Component
18. REDIAL â Data fetching before rendering
HOC exposing three actions to take BEFORE & AFTER
rendering & only CLIENT SIDE.
19. React Router + Redux + Redial: Server Side
1. Call trigger function which is an action creator that returns
a Promise
2. State is update through usual Redux cycle
3. Render the vurrent Route with the current state
4. Get the state and make it available to the client
21. React Router + Redux + Redial: Client Side
1. Listen to navigation events: browserHistory.listen()
2. Match routes to get the component
3. Trigger fetch on the component
4. Render the Component
23. SEO friendly universal web apps - React-Helmet
Isomorphic Web Apps is intended to improve SEOâŠ
.... we need something to manage our meta tags !!!!
React Helmet is the solution for managing the meta tags of a
Route Component
24. React-Helmet - Server Side Rendering
const head = Helmet.rewind(); head.title.toString()