React Router快速入门教程 互动版

服务器端渲染

之前讲解的都是客户端的index.js的处理。现在来看服务器app.js的处理。服务器渲染的核心是React中很简单的一个概念。:

1.我们想要把路由封装成一个模块,以便服务器和客户端都可以请求它。创建文件modules/routes.js,并把路由和组件都写在这里。

import React from 'react'
import { Route, IndexRoute } from 'react-router'
import App from './App'
import Girls from './Girls'
import Boys from './Boys'
import Boy from './Boy'
import Home from './Home'

module.exports = (
  <Route path="/" component={App}>
    <IndexRoute component={Home}/>
    <Route path="/boys" component={Boys}>
      <Route path="/boys/:boyName" component={Boy}/>
    </Route>
    <Route path="/girls" component={Girls}/>
  </Route>
)

2.更新index.js的内容:

import React from 'react'
import { render } from 'react-dom'
import { Router, browserHistory } from 'react-router'
import routes from './modules/routes'

render(
  <Router routes={routes} history={browserHistory}/>,
  document.getElementById('app')
)

3.在服务器上渲染,我们会得到一个空白屏,这是因为服务器渲染是异步的,而路由匹配是同步的。虽然本应用不是加载数据的,但仍可以看到会发生什么。打开app.js,从router中引入 match 和 RouterContext,然后将路由匹配到URL,最后渲染:

// ...
import React from 'react'
import { renderToString } from 'react-dom/server'
import { match, RouterContext } from 'react-router'
import routes from './modules/routes'
// ...

// send all requests to index.html so browserHistory works
app.get('\*', (req, res) => {
  match({ routes: routes, location: req.url }, (err, redirect, props) => {
    const appHtml = renderToString(<RouterContext {...props}/>
    res.send(renderPage(appHtml))
  })
})

function renderPage(appHtml) {
  return \`
    <!doctype html public="storage">
    <html>
    <meta charset=utf-8/>
    <title>My First React Router App</title>
    <link rel=stylesheet href=/index.css>
    <div id=app>${appHtml}</div>
    <script src="/bundle.js"></script>
   \`
}
var PORT = process.env.PORT || 8080
app.listen(PORT, function() {
  console.log('Production Express server running at localhost:' + PORT)
})

4.编译服务器代码

bundle --presets react,es2015 ./app.js -o server.bundle.js

此时运行server.bundle.js,你会看到服务器正在将应用发送到浏览器。当你点击时,你会发现客户端应用接管了处理,而不是向服务器请求界面。很酷吧。