全部源代碼、文檔和圖片都在 github 的倉庫裏,點擊進入倉庫javascript
npm i react-router-dom -S
// containers/News/index.js import React, { Component } from 'react'; class News extends Component { render() { return ( <div> <h1>News Page</h1> </div> ); } } export default News;
<></>
標籤和 <Fragment><Fragment/>
標籤是同樣的,都是一個聚合子元素的一個標籤,不增長真實的 DOM 節點// src/routes.js import React from 'react'; import { Route } from 'react-router-dom'; import Home from './containers/Home'; import News from './containers/News'; export default ( <> <Route path='/' exact component={Home}/> <Route path='/news' component={News}/> </> );
import React from 'react' import { hydrate } from 'react-dom'; import { BrowserRouter } from 'react-router-dom'; import routes from '../routes'; hydrate( <BrowserRouter> {routes} </BrowserRouter>, window.root);
,由於服務端並不知道請求是經過什麼模式,並且服務端也無需知道,服務端只須要根據客戶端發送的請求,作相應的處理便可css
import routes from '../routes'; app.get('*', (req, res) => { let context = {}; let domContent = renderToString( <StaticRouter context={context} location={req.path}> {routes} </StaticRouter> ); // html 的內容不改變 res.send(html); });
app.get('/')
爲 app.get('*')
,由於咱們服務端不只僅是接收同一個路由地址,咱們還有 /news 路由,因此咱們要把根路徑匹配修改成全局匹配。若是不修改成全局匹配呢,也能夠,只不過咱們若是有 100 個路由,咱們就要寫 100 個 app.get('/xxx'),若是你願意的話,也是能夠的原理就是html
http://localhost:3000/hello
路由,那麼咱們的 routes 是匹配不到的,既然匹配不到,那麼 renderToString 渲染的結果就是空,domContent 做爲空值插入 HTML 模板,獲得的就是一個空白頁面// /components/Header/index.js import React, { Component } from 'react'; import { Link } from 'react-router-dom'; class Header extends Component { render() { return ( <nav className="navbar navbar-inverse navbar-fixed-top"> <div className="container-fluid"> <div className="navbar-header"> <a className="navbar-brand">REACT-SSR</a> </div> <div> <ul className="nav navbar-nav"> <li><Link to="/">首頁</Link></li> <li><Link to="/news">新聞</Link></li> </ul> </div> </div> </nav> ); } } export default Header;
// src/client/index.js import React from 'react' import { hydrate } from 'react-dom'; import { BrowserRouter } from 'react-router-dom'; import routes from '../routes'; import Header from '../components/Header'; hydrate( <BrowserRouter> <> <Header/> <div className="container" style={{marginTop: 70}}> {routes} </div> </> </BrowserRouter>, window.root);
// src/server/index.js import Header from '../compoents/Header'; let domContent = renderToString( <StaticRouter context={context} location={req.path}> <> <Header/> <div className="container" style={{marginTop: 70}}> {routes} </div> </> </StaticRouter> );