React-react16和webpack4來寫一個SSR應用

本文的demo倉庫在 https://github.com/qiqingjin/blog/tree/master/React_Redux/,喜歡請star喲~

前面的話

React 16開始重視服務器端渲染,也就是SSR,不再嚴格對比checksum,不知道你的應用升級了麼。
Webpack 4的支持主要看依賴的plugin和loader,目前主流plugin已經支持,可以升級咯。

demo地址https://github.com/qiqingjin/blog/tree/master/React_Redux/demos,使用了React,Redux和Webpack,服務器是Koa,你可以clone這個倉庫,使用 https://github.com/qiqingjin/blog/blob/master/React_Redux/README.md 這個步驟進行本地啓動。

基本思想

簡單來說,我要做的事情就是,寫一套react頁面,服務器端和瀏覽器端都可以把它們轉換成html頁面。當用戶請求某些頁面時,例如:首頁,先進行服務器端渲染,然後返回html頁面。瀏覽器會把服務器端html與瀏覽器端渲染的html頁面對比,並儘量複用服務器端返回的html,展示到瀏覽器上。注意,React 16不再使用checksum進行嚴格校驗。

面臨的問題

  1. 服務器端渲染不會執行ajax請求,如何進行數據請求
  2. 不同的路由,在瀏覽器端會請求不同的數據,如何在服務器端根據路由來進行數據處理

數據請求

react-dom/server提供了一個renderToString方法,可以把react的虛擬dom,也就是react component的類,轉換成html。我們只要在調用這個方法之前,提前執行需要在瀏覽器端執行的請求就好,看代碼:

// demos/server/server.js
const {data: todosData} = await axios.get('http://localhost:667/rest/todos');

然後需要獲取react組件,我這裏使用koa,node端不支持import等方法,需要用webpack把react組件編譯,注意,服務器端編譯的config配置和瀏覽器端編譯的config略有不同,請看demos/client/webpack.config.jsdemos/client/webpack.config.ssr.js。獲取react組件的代碼:

// demos/server/server.js
const indexBundle = require('./dist/main.ssr');
const indexApp = indexBundle.__esModule ? indexBundle.default : indexBundle;

獲取react組件後,需要把數據注入到redux的createStore方法中,再傳給react組件,保證react組件中的storedispatch等方法。

// demos/server/server.js
const store = indexApp.createStore(initData);
const instance = indexApp.createApp(store);
const todosStr = ReactDOMServer.renderToString(instance);

最後,需要把數據放到window對象上,讓瀏覽器端用來渲染瀏覽器端html,然後與服務器端html對比,儘量複用。

// demos/server/server.js
const syncScript = `<script id="server-data">window._SERVER_DATA=${JSON.stringify(initData)}</script>`;
const $ = await loadHTMLTemplate(path.resolve(__dirname, '../client/dist/index.html'));
$('#app').html(todosStr);
$('head').append(syncScript);

路由處理

這個地方目前我看到的處理方法有:
1. 使用react-routermatch方法,這個方案比較常見
2. 把頁面分成多個thunk,並綁定到客戶的的路由文件中,在renderToString之前dispatch這些異步方法,從而將數據更新到redux的store中,請參考

這裏我並沒有寫在我的代碼中,如果你想嘗試,可以clone我的倉庫,自己進行優化。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章