React服務器渲染最佳實踐

源碼地址:https://github.com/skyFi/dva-starterjavascript

React服務器渲染最佳實踐css

dva-starter

完美使用 dva react react-router,最好用的ssr腳手架,服務器渲染最佳實踐html

歡迎 Fork ,Issue 交流各類想法java

  • 努力在最佳的路上,不斷完善,建議star或watch.
  • 有想法就Fork, Pull requests ,我很耐 操.

Usage

安裝redisreact

$ brew install redis

啓動redisgit

$ brew services start redis

準備配置文件github

  • 將config.example.js拷貝一份config.js並修改成你想要的配置
  • 共兩個地方

運行redis

 'production': $ npm run start
'development': $ npm run dev

服務器渲染須要的initData

對於服務器渲染須要獲取的數據,放置的model中的initData中,結構和effects同樣,也同樣能夠在頁面中像調用effects同樣調用,你所須要關心的僅僅是哪些數據須要首屏出現,把它從effects中移到initData中便可,其餘的你都不須要關心了,是否是很爽,哇哈哈shell

export default ModelHelper({
  namespace: 'user',
  state: [
    {
      list: undefined,
    }
  ],
  reducers: {
    list(state, { list }) {
      return { ...state, list };
    },
  },
  effects: {
    *fetchTodoList(action, { call, put }) {
      const res = yield call(fetchTodoList);
      if (res) {
        yield put({
          type: 'list',
          list: res
        });
      } else {
        throw new Error(`Init data Error: fetchTodoList.`);
      }
    },
  },
  initData: {
    *fetchAnotherList({}, { call, put }) {
      const res = yield call(fetchAnotherList);
      if (res) {
        yield put({
          type: 'list',
          list: res
        });
      } else {
        throw new Error(`Init data Error: fetchAnotherList.`);
      }
    },
  },
})

魔法全局變量initialState的消失

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <link rel="stylesheet" href="/index.css" />
</head>
<body>
  <div id="root">
    <div>
      <div data-reactroot="" data-reactid="1" data-react-checksum="-35862160"><div data-reactid="2"><h1 data-reactid="3"><!-- react-text: 4 -->App _ <!-- /react-text --><!-- react-text: 5 --><!-- /react-text --></h1><h3 data-reactid="6">About</h3><h3 data-reactid="7">點我試試</h3><h2 class="title" data-reactid="8">User</h2><div data-reactid="9"><!-- react-text: 10 -->- <!-- /react-text --><!-- react-text: 11 -->周靜<!-- /react-text --></div><div data-reactid="12"><!-- react-text: 13 -->- <!-- /react-text --><!-- react-text: 14 -->侯軍<!-- /react-text --></div><div data-reactid="15"><!-- react-text: 16 -->- <!-- /react-text --><!-- react-text: 17 -->郭超<!-- /react-text --></div><div data-reactid="18"><!-- react-text: 19 -->- <!-- /react-text --><!-- react-text: 20 -->喬濤<!-- /react-text --></div><div data-reactid="21"><!-- react-text: 22 -->- <!-- /react-text --><!-- react-text: 23 -->楊超<!-- /react-text --></div><div data-reactid="24"><!-- react-text: 25 -->- <!-- /react-text --><!-- react-text: 26 -->萬娟<!-- /react-text --></div><div data-reactid="27"><!-- react-text: 28 -->- <!-- /react-text --><!-- react-text: 29 -->何超<!-- /react-text --></div><div data-reactid="30"><!-- react-text: 31 -->- <!-- /react-text --><!-- react-text: 32 -->戴秀蘭<!-- /react-text --></div><div data-reactid="33"><!-- react-text: 34 -->- <!-- /react-text --><!-- react-text: 35 -->孫秀英<!-- /react-text --></div><div data-reactid="36"><!-- react-text: 37 -->- <!-- /react-text --><!-- react-text: 38 -->鄒超<!-- /react-text --></div><div data-reactid="39"><!-- react-text: 40 -->- <!-- /react-text --><!-- react-text: 41 -->蘇剛<!-- /react-text --></div><div data-reactid="42"><!-- react-text: 43 -->- <!-- /react-text --><!-- react-text: 44 -->毛剛<!-- /react-text --></div><div data-reactid="45"><!-- react-text: 46 -->- <!-- /react-text --><!-- react-text: 47 -->蕭麗<!-- /react-text --></div><div data-reactid="48"><!-- react-text: 49 -->- <!-- /react-text --><!-- react-text: 50 -->胡勇<!-- /react-text --></div><div data-reactid="51"><!-- react-text: 52 -->- <!-- /react-text --><!-- react-text: 53 -->毛剛<!-- /react-text --></div><div data-reactid="54"><!-- react-text: 55 -->- <!-- /react-text --><!-- react-text: 56 -->賀強<!-- /react-text --></div></div></div>
    </div>
  </div>
  <script type="text/javascript" src="/states/YT50C6TStrTsitaHF0gwkxpyslhAYJAZ1489673610988.js"></script>
  <script src="/index.js"></script>
</body>
</html>

最第一版本採用了一個全局變量initialState來將服務器渲染時得到的初始化states同步到客戶端初始化的states,這個方法有個弊端,npm

  • 第一,暴漏個全局的變量,不爽;

  • 第二,不夠優雅;

  • 第三,使得html頁面擁有大段大段的script,這會下降你的網站在百度的權重!。

因此,這裏將states放到了一個redis中緩存,避免了一些問題,但,偉大的同性交流平臺啊,這必定有更好的解決辦法,若是有,那你必定要告訴我,翹首期盼之!!

目前最佳方案:

  1. 緩存住準備好的初始化states
module.exports.set = function *(stateString) {
  const key = randomstring.generate() + Date.now();
  yield cache.setexAsync(`${cache.prefix}:state:${key}`, EXPIRE, stateString);
  return key;
};
  1. 頁面加載
<script type="text/javascript" src="/states/${stateKey}.js"></script>
  1. 路由截取
app.use('/states/(:key).js', stateServe);
  1. 頁面同步states
const app = createApp({
  history: browserHistory,
  initialState: JSON.parse(window.states),
}, { router, models });
  1. 刪除states
delete window.states;

最後,若是你有更好的解決方案,請必定要告訴我,不甚感激!

相關文章
相關標籤/搜索