最近折騰了下React的ssr項目的搭建,以前折騰過一次沒有太多的進展。此次從新開始搭建react的項目架構。項目源碼:https://github.com/rt-zhangxuefei/react-ssr-templatecss
特別感謝:慕課網的Delllee的課程。這裏我使用了saga代替thunk,中間也遇到了一些坑,中間層代理使用了http-proxy-middleware。文章記錄我搭建過程當中遇到的一些問題:html
ssr的過程前端
1)訪問首屏時(任何url首次經過瀏覽器打開),請求到達node服務端node
2)node服務根據訪問的url匹配路由表(routte目錄下的index.js)react
3)匹配到的路由裏面調用組件的loadData(本身定義的,用來獲取數據),有須要獲取數據的組件才添加一個loadData方法,這裏匹配的路由多是多個,因此會有多個loadData的方法,並且這些方法都是異步的(sagas)。ios
4)待全部異步操做完成,調用renderToString方法渲染出html字符串git
5)express服務發送html字符串給瀏覽器(包含數據)和已經渲染好的dom字符串github
6)瀏覽器獲取到html字符串解析展現網頁內容(ttfp)ajax
7)瀏覽器根據script標籤裏面的src地址請求服務器,下載包含react客戶端js文件express
8)解析js,react執行,接管了整個頁面的交互控制以及渲染
9)結束
項目結構如圖
項目簡介
本身模擬了幾個接口(登陸,判斷登陸,獲取文章列表,評論列表),登陸之後才能查看評論
支持less,css module
什麼是注水和脫水
服務器端經過路由匹配出的組件的loadData方法(sagas)填充store,經過html字符串裏面注入script標籤引入變量的方式把store傳給了瀏覽器,這個就是脫水。瀏覽器加載了包含reactjs的代碼之後,把服務器注入過來的js對象的數據做爲默認state傳入createStore方法完成脫水過程。
服務器端渲染時react-router使用StaticRouter無狀態路由
這裏有個很重要的屬性context,以下:
這個context參數會貫穿到瀏覽器和服務器端,成爲一個數據交互的橋樑。好比判斷前端路由重定向,404跳轉等都是經過context做爲判斷來實現的。
css渲染
在具備樣式的組件須要經過生命週期鉤子注入css,讓服務器端獲取到而且渲染出來,這裏就是一個應用(context做爲數據橋樑)
組件的loadData(方法名稱本身定義)
sagas就是store目錄下的sagas
node做爲中間層
全部的ajax請求都是經過node做爲中間層來轉發,這裏使用了
axios對象的createInstance方法
服務器端使用的axios實例和瀏覽器端使用的axios實例不同,做爲參數傳遞給sagas,這裏須要注意傳參的方式:
服務器端使用:
客戶端使用:
之因此可以這樣作是由於watch sagas都是在瀏覽器端調用的(好比經過生命週期鉤子,或者點擊事件等),而loadData是服務器端調用獲取數據用來填充store的。
造輪子?
雖然有了next.js,但有時本身造輪子有時是須要的。固然next.js是很是受歡迎的,值得用來開發實際的項目
結尾
再次感謝DellLee老師的課程。花了2周的時間,完成了一個react-ssr項目架構,項目裏面還有2個未解決的問題,一個是css在服務器和客戶端都渲染了一次,另一個就是code splitting或按需加載的問題。但願在後續的學習過程當中可以解決遺留的問題。若是你解決,請留言告訴我!