javascript - Server side rendering with react, react-router, and express -


i'm trying set server-side rendering react app , i'm trying use great react-router module allow handle non-js situations (some crawlers, when user had js turned off reason). however, i'm running trouble. i've been using great response here https://stackoverflow.com/a/28558545/3314701 guide of sorts, i'm getting strange errors thrown @ me. persistent syntax error when trying use react.rendertostring(). setting server-side rendering incorrectly, missing obvious, or else?

my setup:

really basic express server

require('babel/register');  var app = express();   // misc. express config...  var router = require('react-router'),     routes = require('../jsx/app').routes,     react = require('react');   app.use(function(req, res, next) {   var router = router.create({location: req.url, routes: routes});   router.run(function(handler, state) {     console.log(handler);     var html = react.rendertostring(<handler/>);     return res.render('react_page', {html: html});   }); }); 

top-level react <app/> component

// shims require('intl'); require('es5-shim');  var react = require('react/addons'),   router = require('react-router'),   nav = require('./nav'),   injecttapeventplugin = require("react-tap-event-plugin"),     window.react = react; // export http://fb.me/react-devtools  // intl var reactintl = require('react-intl'),   intlmixin = reactintl.intlmixin;  var route = router.route,   defaultroute = router.defaultroute,   notfoundroute = router.notfoundroute,   routehandler = router.routehandler;   var app = react.createclass({       mixins: [intlmixin],        getinitialstate: function() {         return {           connected: false,           loaded: false,           user: true         };       },       render: function() {           return (              <div classname="container-fluid">               <nav/>               <routehandler/>               <footer/>             </div>       );   }  });  var routes = ( <route name="home" path="/" handler={app}>     <defaultroute name="welcome " handler={welcome}/>     <route name="bar" path="/bar" handler={bar}>     <route name="foo" path="/foo" handler={foo}></route>  </route> );  router.run(routes, router.historylocation , function(handler) {   react.render(<handler/>, document.getelementbyid('app')); });  module.routes = routes; 

output:

flo-0,1,2 (err):       <div classname="progressbar-container" > flo-0,1,2 (err):       ^ flo-0,1,2 (err): syntaxerror: unexpected token < flo-0,1,2 (err):     @ exports.runinthiscontext (vm.js:73:16) flo-0,1,2 (err):     @ module._compile (module.js:443:25) flo-0,1,2 (err):     @ module._extensions..js (module.js:478:10) flo-0,1,2 (err):     @ object.require.extensions.(anonymous function) [as .js] (/users/user/code/foobar/apps/flo/node_modules/babel/node_modules/babel-core/lib/babel/api/register/node.js:161:7) flo-0,1,2 (err):     @ module.load (module.js:355:32) flo-0,1,2 (err):     @ function.module._load (module.js:310:12) flo-0,1,2 (err):     @ function.<anonymous> (/users/user/.nvm/versions/node/v0.12.4/lib/node_modules/pm2/node_modules/pmx/lib/transaction.js:62:21) flo-0,1,2 (err):     @ function.cls_wrapmethod (/users/user/code/foobar/apps/bar/node_modules/newrelic/lib/shimmer.js:230:38) flo-0,1,2 (err):     @ function.<anonymous> (/users/user/code/foobar/apps/bar/node_modules/pmx/lib/transaction.js:62:21) flo-0,1,2 (err):     @ module.require (module.js:365:17) flo-0,1,2 (err):     @ require (module.js:384:17) 

so, ended solving 1 myself. error getting un-rendered nested component, why js engine complaining random < char.

and express setup. aren't aware of how react can used server-side rendering, it's straightforward: node or io.js can used call react's rendertostring() method on component , sending requesting client. you've heard benefits approach brings already, don't know:

  1. you more seo-friendliness, though google can execute js in it's crawlers; pretty safer bet
  2. fallback non-js situations. if app script loading slowly, can still render actual page client , not make them wait while staring @ blank screen. allows js disabled on browser still interact app part; links still work, forms can still submit, &c.
  3. you can additional benefits of code-sharing between client , server. there's nothing incredible aside fact complexity decreased and, such, benefits of decreased complexity (potentially less coupling, easier maintainability, greater simplicity in structure, isomorphic-ness, &c.)
  4. a further side benefit ability use react-router's html5 history api instead of annoying hash-fragment stuff have otherwise use.

you crazy approach , handle things placeholders app while loads or provide other feedback mechanisms slow-loading state (a la facebook while loads).

the basic approach operates in following manner:

  1. upon bootstrap, node app instantiates react-router instance based on routes.jsx
  2. request goes server, uses express' req.path provide route string react-router handle.
  3. react router matches provided route , tries render corresponding component express send back.
  4. react sends down html response , client gets paint regardless of speed of app script. serve ours on great cdn, best distribution , compression slow networks still otherwise leave people temporarily blank screen.
  5. having loaded needed app script, react can use same routes.jsx file take on , generate html react-router here on out. benefit here app code can cached , future interactions won't have rely on call.

one more point worth noting: use webpack bundle react code , browser.jsx entry point. before refactoring server-side rendering app.jsx; might need re-configure structure accommodate gets rendered where. :)

le code:

browser.jsx

const react = require('react'); const router = require('react-router').router; const hist = require('history'); const routes = require('./routes');  const newhistory = hist.createhistory();  react.render(<router history={newhistory}>{routes}</router>, window.document); 

app.js (express server):

//...other express configuration  const routes = require('../jsx/routes'); const react = require('react'); const {routingcontext, match} = require('react-router'); const hist = require('history');  app.use((req, res, next) => {   const location = hist.createlocation(req.path);   match({     routes: routes,     location: location,   }, (err, redirectlocation, renderprops) => {     if (redirectlocation) {       res.redirect(301, redirectlocation.pathname + redirectlocation.search);     } else if (err) {       console.log(err);       next(err);       // res.send(500, error.message);     } else if (renderprops === null) {       res.status(404)         .send('not found');     } else {       res.send('<!doctype html>' + react.rendertostring(<routingcontext {...renderprops}/>));     }   }); });      //...other express configuration 

routes.jsx

<route path="/" component={app}>   <defaultroute component={welcome}/>   <route path="dashboard" component={dashboard}/>   <route path="login" component={login}/> </route> 

app.jsx

<html> <head>   <link rel="stylesheet" href="/assets/styles/app.css"/> </head>   <body>     <navigation/>     <routehandler/>     <footer/>   <body/> </html> 

helpful links:


Comments

Popular posts from this blog

javascript - Bootstrap Popover: iOS Safari strange behaviour -

Magento/PHP - Get phones on all members in a customer group -

session - Logging Out Using PHP -