Successfully reported this slideshow.

Universal JS Applications with React

0

Share

1 of 25
1 of 25

More Related Content

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all

Universal JS Applications with React

  1. 1. REACTJS UNIVERSAL JS APPLICATION WITH 05/2017
  2. 2. ABOUT ME TRẦN TRỌNG THANH ▸ CTO & Co-founder NauStud.io ▸ 4 years with ActionScript, ex-Pycorian ;) ▸ 5 years with JavaScript ▸ Have worked with ReactJS, Angular 2, and learning VueJS ▸ SaigonJS FB group curator (bit.ly/saigonjs) ▸ Contact: Twitter/Facebook/Github /trongthanh Nau is hiring! 😎❤☕
  3. 3. UNIVERSAL JS APPLICATION WITH REACTJS A BRIEF HISTORY OF WEB APPS ▸ 1992 - Static HTML ▸ 1993 - Server side rendered HTML (CGI protocol) ▸ 1995 - LiveScript (a.k.a JavaScript) in Netscape Nav 2.0 ▸ 1997 - Dynamic HTML, Internet Explorer 4 ▸ 2005 - AJAX web apps ▸ 2010-ish - JS frameworks and Single page apps (SPA)
  4. 4. A BRIEF HISTORY OF WEB APPS WHY SPA? ▸ Instant responses on the UI* ▸ No page refresh, allows page transitions ▸ Less overheads at server side ▸ App-like experience ▸ Foundation for Hybrid mobile apps ▸ More emphasis at Front End, enables back-end-less
  5. 5. A BRIEF HISTORY OF WEB APPS THE ACHILLES’ HILL OF SPA (2015 A.D.) 😞 SEO 😞 First meaningful paint 😞 no-script <!doctype html> <html lang="en"> <head> <title>My Awesome Single Page App</title> <meta charset="utf-8"> <meta name="viewport" content="..."> <link rel="stylesheet" href="styles.min.css"> </head> <body> <div id="root" style="height: 100%"></div> <script src="bundle.js"></script> </body> </html> * Code sample from react-redux-starter-kit
  6. 6. A BRIEF HISTORY OF WEB APPS OBVIOUS SOLUTION? Render content HTML at server-side MORE PROBLEMS? 😞 Duplicated rendering logic at server side 😞 Double work of template maintenance 😞 Flash of updated content 😞 All the relief of SPA for backend is gone
  7. 7. THE RISE OF 
 UNIVERSAL JAVASCRIPT APPLICATIONS
  8. 8. WHAT IS A UNIVERSAL JS APPLICATION? ▸ Used to be called Isomorphic JS Applications ▸ There are portions of JS run on both client and server (hence universal / isomorphic) ▸ Server-side rendered HTML ▸ Server-enabled History Push State
  9. 9. TRADITIONAL SPA WITH REDUX ARCHITECTURE
  10. 10. UNIVERSAL JS APP WITH REDUX ARCHITECTURE
  11. 11. CODE WALKTHROUGH UNIVERSAL REACT APP Based from a simple Universal Redux template
  12. 12. UNIVERSAL - CONTAINER COMPONENT /*...*/ import { connect } from 'react-redux' import { loadQuestionDetail } from 'actions/questions' import { browserHistory } from 'react-router' class Question extends Component { static fetchData({ store, params, history }) { let { id } = params return store.dispatch(loadQuestionDetail({ id, history })) } componentDidMount() { let { id } = this.props.params this.props.loadQuestionDetail({ id, history: browserHistory }) } render() { return (<div> {/* stuff... */}</div>) } } /*...*/ export default connect(mapStateToProps, { loadQuestionDetail })(Question)
  13. 13. SERVER - EXPRESS UNIVERSAL RENDERER MIDDLEWARE import React from 'react' import ReactDOMServer from 'react-dom/server' import { useRouterHistory, RouterContext, match } from 'react-router' import { createMemoryHistory, useQueries } from 'history' import configureStore from 'store/configureStore' import createRoutes from 'routes/index' import { Provider } from 'react-redux' server.get('*', (req, res, next) => { let history = useRouterHistory(useQueries(createMemoryHistory))() let store = configureStore() let routes = createRoutes(history) let location = history.createLocation(req.url) match({ routes, location }, (error, redirectLocation, renderProps) => { /* cont... */ }) }) //end server.get('*')
  14. 14. SERVER - EXPRESS UNIVERSAL RENDERER MIDDLEWARE /*...*/ server.get('*', (req, res, next) => { /* ... */ match({ routes, location }, (error, redirectLocation, renderProps) => { /* handle error & redirectLocation... */ function getReduxPromise() { /*...*/ } getReduxPromise().then(()=> { let reduxState = escape(JSON.stringify(store.getState())) let html = ReactDOMServer.renderToString( <Provider store={store}> { <RouterContext {...renderProps}/> } </Provider> ) let metaHeader = Helmet.rewind() // always render the index template res.render('index', { metaHeader, html, reduxState, scriptSrcs, styleSrc }) }) .catch((err)=> { Helmet.rewind() next(err) }) }) }) //end server.get('*')
  15. 15. SERVER - EXPRESS UNIVERSAL RENDERER MIDDLEWARE function getReduxPromise() { let { query, params } = renderProps let comp = renderProps.components[renderProps.components.length - 1].WrappedComponent let promise = comp.fetchData ? comp.fetchData({ query, params, store, history }) : Promise.resolve() return promise }
  16. 16. SERVER - EXPRESS UNIVERSAL RENDERER MIDDLEWARE /*...*/ server.get('*', (req, res, next) => { /* ... */ match({ routes, location }, (error, redirectLocation, renderProps) => { /* handle error & redirectLocation... */ function getReduxPromise() { /*...*/ } getReduxPromise().then(()=> { let reduxState = escape(JSON.stringify(store.getState())) let html = ReactDOMServer.renderToString( <Provider store={store}> { <RouterContext {...renderProps}/> } </Provider> ) // always render the index template res.render('index', { html, reduxState, /*...*/ }) }) .catch((err)=> { next(err) }) }) }) //end server.get('*')
  17. 17. SERVER - EXPRESS INDEX TEMPLATE <!DOCTYPE html> <html> <head> <%# metaHeader and stylesheet stuff, omit for clarity...%> </head> <body> <div id="root"><%- html %></div> <script type="text/javascript" charset="utf-8"> window.__REDUX_STATE__ = '<%= reduxState %>'; </script> <% scriptSrcs.forEach(function(src){ %> <script src="<%= src %>"></script> <% }) %> </body> </html>
  18. 18. CLIENT - REACT APP.JS /*...*/ import ReactDOM from 'react-dom' import { browserHistory } from 'react-router' import { Provider } from 'react-redux' import createRoutes from 'routes/index' import configureStore from 'store/configureStore' let initialState = {} if (window.__REDUX_STATE__) { try { initialState = JSON.parse(unescape(__REDUX_STATE__)) } catch (e) { /*catch error*/ } } const store = configureStore(initialState) ReactDOM.render(( <Provider store={store}> { createRoutes(browserHistory) } </Provider> ), document.getElementById('root'))
  19. 19. DEMO
  20. 20. UNIVERSAL JS APPLICATION WE HAVE SOLVED: 👍 SEO 👍 First meaningful paint 👍 no-script 👍 Code reuse
  21. 21. WAIT. 
 THERE’S MORE
  22. 22. NEXT.JS INTRODUCING
  23. 23. IN 2 MINUTES LET’S CREATE A UNIVERSAL APP
  24. 24. Q&A
  25. 25. READ MORE REFERENCES ▸ https://medium.com/@mjackson/universal-javascript-4761051b7ae9 ▸ https://medium.com/node-security/the-most-common-xss-vulnerability-in-react-js- applications-2bdffbcc1fa0 ▸ https://github.com/mz026/universal-redux-template ▸ https://github.com/erikras/react-redux-universal-hot-example ▸ https://learnnextjs.com

×