服務端渲染react+mobx+webpack+express實戰(同時也支持客戶端渲染)

目前絕大多數網站仍是一個多頁的結構,但其實一個網站已經徹底能夠作成一個spa,好比youtube就是一個spa,最近公司項目都是採用react+mobx服務端渲染的單頁面應用的形式,踩了一些坑,有一些本身的體驗,因此把項目抽了出來去掉了業務代碼,留了一個架子分享一下。前端

項目github地址react

目前react主流的狀態管理使用的比較多的是redux,我司以前有個項目也是react+redux,從我我的使用下來的感覺來講,對於絕大多數的前端應用場景,mobx遠比redux更合適,更簡單使用,更容易上手。git

效果

登錄,註冊

登錄

添加item到列表中

列表

若是路由中沒有的頁面,處理404

圖片描述

如何使用

git clone git@github.com:L-x-C/isomorphic-react-with-mobx.git
cd isomorphic-react-with-mobx
npm install

Dev (客戶端渲染)

npm start
open http://localhost:3000

Production (服務端渲染)

npm run server
open http://localhost:20000

一些常常會遇到的狀況

如何在服務端獲取數據?

在每一個component中增長一個onEnter,用一個promise來處理,在這個promise中發起一個action,改變mobx中的states值github

@action
static onEnter({states, pathname, query, params}) {
    return Promise.all([
      menuActions.setTDK(states, '列表'),
      jobActions.fetchJobList(states, query)
    ]);
}

之因此能這麼作,是由於在serverRender中有一個onEnter的預處理,會根據component的嵌套從最外層一直遍歷到最裏層的onEnter,並執行其中的的方法npm

import async from 'async';

export default (renderProps, states) => {
  const params = renderProps.params;
  const query = renderProps.location.query;
  const pathname = renderProps.location.pathname;

  let onEnterArr = renderProps.components.filter(c => c.onEnter);
  return new Promise((resolve, reject) => {
    async.eachOfSeries(onEnterArr, function(c, key, callback) {
      let enterFn = c.onEnter({states, query, params, pathname});
      if (enterFn) {
        enterFn.then(res => {
          if (res) {
            //處理Promise回調執行,好比登錄
            res.forEach((fn) => {
              if (Object.prototype.toString.call(fn) === '[object Function]') {
                fn();
              }
            });
          }

          if (key === (onEnterArr.length - 1)) {
            resolve();
          }

          callback();
        }).catch(err => {
          reject(err);
        });
      } else {
        callback();
      }
    });
  });
};

如何在服務端設置tdk(title, description, keywords)?

這其實在上一個問題中就已經出現了,onEnter中有一個setTDK(states, t, d, k)的方法,使用他就能夠設置tdk的值redux

如何在服務端進行跳轉?

在瀏覽器環境中,咱們能夠設置window.location.href = url來進行跳轉。
可是在服務器環境中,並無window和document這2個對象,因此咱們在服務器環境中拋出一個異常,而後捕獲到以後進行302跳轉。
具體能夠看src/helpers/location.js, 中的redirect function
他會自動判斷當前環境,來選擇使用哪種跳轉promise

import {redirect} from './helpers/location';

@action
static onEnter({states, query, params}) {
    redirect('http://www.xxx.com');
}

mobx的原理及使用就不在這裏作詳細的介紹了,網上搜一搜有不少。
我相信咱們所採用的一些方法也許並非最完美的解法,若是有更好的歡迎來github中提issue探討交流,互相學習~項目地址在此瀏覽器

相關文章
相關標籤/搜索