二、koa+React服務(wù)端渲染:添加路由

目標(biāo)

上一次做了一個(gè)簡(jiǎn)單的hello world盆昙,這個(gè)我給單頁(yè)面應(yīng)用加入路由羽历,這里我用的是react-router v4。這里為了簡(jiǎn)單就只設(shè)置兩個(gè)頁(yè)面淡喜,一個(gè)home頁(yè)面秕磷,一個(gè)about頁(yè)面

項(xiàng)目設(shè)置

安裝路由包

npm install react-router react-router-dom --save

編寫應(yīng)用

  1. 創(chuàng)建home和about組件
    <root>/app/web/component/home/home.js
import React from 'react';

const Home = () => {
  return (
    <div>Home</div>
  );
};

export default Home;

<root>/app/web/component/about/about.js

import React from 'react';

const About = () => {
  return (
    <div>About</div>
  );
};

export default About;
  1. 設(shè)置瀏覽器端路由
    <root>/app/web/component/app/admin.js
import React from 'react';
import { Route, Link } from 'react-router-dom';
import Home from '../home/home';
import About from '../about/about';

const App = ({ msg }) => {
  return (
    <div>
      <div>Hello { msg }</div>
      <ul>
        <li>
          <Link to="/admin">Home</Link>
        </li>
        <li>
          <Link to="/admin/about">About</Link>
        </li>
      </ul>
      <hr />
      <Route exact path="/admin" component={Home} />
      <Route path="/admin/about" component={About} />
    </div>
  )
};

export default App;

這樣當(dāng)訪問(wèn)/admin的時(shí)候就會(huì)渲染home組件,訪問(wèn)/admin/about就會(huì)渲染about組件
然后我們期望瀏覽器端是使用H5的history API實(shí)現(xiàn)路由炼团,所以我們使用BrowserRouter澎嚣,修改
<root>/app/web/page/browser/admin.js

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';

import AdminApp from '../../component/app/admin';

ReactDOM.hydrate((
  <BrowserRouter {...window.__STATE__}>
    <AdminApp {...window.__STATE__}/>
  </BrowserRouter>
), document.getElementById('root'));
  1. 設(shè)置服務(wù)端路由
    首先,我們要確保當(dāng)瀏覽器訪問(wèn)/admin 和 /admin/about這樣的以/admin開頭的路由的時(shí)候瘟芝,服務(wù)器能夠渲染出頁(yè)面易桃。也就是說(shuō),當(dāng)訪問(wèn)/admin/about的時(shí)候模狭,服務(wù)器不能返回404颈抚。我們修改
    <root>/app/router.js
const admin = require('./controller/admin');

module.exports = app => {
  const { router } = app;
  // 匹配所有/admin開頭的url
  router.get('/admin(.*)', admin.admin);
};

/admin(.*) 代表所有訪問(wèn)以/admin開頭的url時(shí),都會(huì)被admin這個(gè)controller處理嚼鹉。這樣就不會(huì)返回404了贩汉。
當(dāng)然,光是不反回404還是不夠的锚赤,我們需要react根據(jù)url渲染出對(duì)應(yīng)的html文本匹舞,我們還需要修改
<root>/app/web/page/server/admin.js

import React from 'react';
import { StaticRouter } from 'react-router-dom';

import AdminLayout from '../../component/layout/admin_layout';
import AdminApp from '../../component/app/admin';

const server = context => {
  return (
    <AdminLayout state={context}>
      <StaticRouter {...context} location={ context.url } >
        <AdminApp {...context} />
      </StaticRouter>
    </AdminLayout>
  )
};
export default server;

上面代碼關(guān)鍵點(diǎn)在于給StaticRouter傳入了一個(gè)context.url,但是目前為止线脚,我們還沒(méi)有再服務(wù)端傳入這個(gè)屬性赐稽,所有需要修改
<root>/app/middleware/react_view.js

const assert = require('assert');
const path = require('path');
const fs = require('fs');
const ReactDOMServer = require('react-dom/server');

const defaults = {
  view: path.resolve(process.cwd(), 'view'),
  extname: 'js'
};

module.exports = (options, app) => {
  options = options || {};
  options = Object.assign({}, defaults, options);
  assert(typeof options.view === 'string', 'options.view required, and must be a string');
  assert(fs.existsSync(options.view), `Directory ${options.view} not exists`);
  options.extname = options.extname.trim().replace(/^\.?/, '.');
  app.context.render = function (filename, _context) {
    if (!path.extname(filename)) {
      filename += options.extname;
    }
    let filepath = path.isAbsolute(filename) ? filename : path.resolve(options.view, filename);
    const context = Object.assign({}, this.state, _context);
    // 添加 url 屬性
    if (!context.url) {
      context.url = this.url;
    }
    try {
      let view = require(filepath);
      view = view.default || component;
      this.body = ReactDOMServer.renderToString(view(context));
      this.type = 'html';
    } catch (err) {
      err.code = 'REACT';
      throw err;
    }
  }
};

目前為止叫榕,路由就加上了,執(zhí)行命令

npm run build && npm run start

在瀏覽器輸入http://localhost:3000/admin應(yīng)該能看到

輸入http://localhost:3000/admin/about應(yīng)該能看到

項(xiàng)目地址:https://github.com/leitc/isomorphic-react/tree/0.2

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末姊舵,一起剝皮案震驚了整個(gè)濱河市晰绎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌括丁,老刑警劉巖荞下,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異史飞,居然都是意外死亡尖昏,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門构资,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)抽诉,“玉大人,你說(shuō)我怎么就攤上這事吐绵〖L剩” “怎么了?”我有些...
    開封第一講書人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵己单,是天一觀的道長(zhǎng)巍沙。 經(jīng)常有香客問(wèn)我,道長(zhǎng)荷鼠,這世上最難降的妖魔是什么句携? 我笑而不...
    開封第一講書人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮允乐,結(jié)果婚禮上矮嫉,老公的妹妹穿的比我還像新娘。我一直安慰自己牍疏,他們只是感情好蠢笋,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著鳞陨,像睡著了一般昨寞。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上厦滤,一...
    開封第一講書人閱讀 51,763評(píng)論 1 307
  • 那天援岩,我揣著相機(jī)與錄音,去河邊找鬼掏导。 笑死享怀,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的趟咆。 我是一名探鬼主播添瓷,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼梅屉,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了鳞贷?” 一聲冷哼從身側(cè)響起坯汤,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎搀愧,沒(méi)想到半個(gè)月后玫霎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡妈橄,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了翁脆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片眷蚓。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖反番,靈堂內(nèi)的尸體忽然破棺而出沙热,到底是詐尸還是另有隱情,我是刑警寧澤罢缸,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布篙贸,位于F島的核電站,受9級(jí)特大地震影響枫疆,放射性物質(zhì)發(fā)生泄漏爵川。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一息楔、第九天 我趴在偏房一處隱蔽的房頂上張望寝贡。 院中可真熱鬧,春花似錦值依、人聲如沸圃泡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)颇蜡。三九已至,卻和暖如春辆亏,著一層夾襖步出監(jiān)牢的瞬間风秤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工扮叨, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留唁情,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓甫匹,卻偏偏與公主長(zhǎng)得像甸鸟,于是被迫代替她去往敵國(guó)和親惦费。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容