摘要:之前做的一個應用,最近把首頁改成了服務端渲染的形式,過程還是很周折的,踩到了不少坑,記錄一些重點,希望有所幫助前端使用的技術棧升級到升級到服務項目地址喜歡的給個,感謝。。。。。。。
之前react做的一個應用,最近把首頁改成了服務端渲染的形式,過程還是很周折的,踩到了不少坑,記錄一些重點,希望有所幫助前端使用的技術棧
react、react-dom 升級到 v16
react-router-dom v4
redux red-sage
antd-mobile 升級到 v2
ssr服務 express
項目地址,喜歡的給個star,感謝。。。。。。。
訪問地址(手機模式) 非服務端渲染 服務端渲染 效果對比 前后處理流程對比 react下ssr的實現方式React下同構的解決方案有next.js、react-server等,這里,因為這個項目之前已經采用create-react-app、redux做完了,只是想在現有系統基礎上把首頁改成服務端直出的方式,就選擇了webpack-isomorphic-tools這個模塊
webpack-isomorphic-tools介紹如果我們想在現有React系統中引入同構,首先要解決的一個重要問題是:代碼中我們import了圖片,svg,css等非js資源,在客戶端webpack的各種loader幫我們處理了這些資源,在node環境中單純的依靠babel-regisiter是不行的,執行renderToString(
而webpack-isomorphic-tools就幫助我們處理了這些非js資源,在客戶端webpack構建過程中,webpack-isomorphic-tools作為一個插件,生成了一份json文件,形如:
有了這份映射文件,在同構的服務端,renderToString(
比如我們有一個組件:
const App =()=>{ return ),就生成正確的 ) //得到填滿數據的標簽
拼接html
注意,上面說的webpack-isomorphic-tools中生成的json文件中有js,css的對應關系,這里我訪問那個json文件得到js、css的路徑,拼到html中
還要返回store中保存的狀態,供客戶端js createStore使用
在客戶端js中
const sagaMiddleware = createSagaMiddleware() const store = createStore( reducer, window.__INITIAL_STATE__, applyMiddleware(sagaMiddleware) ) sagaMiddleware.run(rootSaga)路由
在做同構的時候不能用BrowserRouter,要使用無狀態的StaticRouter,并結合location和context兩個屬性
有這樣的路由結構
//默認跳到/home,其他的該到哪到哪}>
server端的代碼要這樣
const context = {} const html = renderToString() // 中訪問/,重定向到/home路由時 if (context.url) { res.redirect("/home") return }
StaticRouter可以根據request來的url來指定渲染哪個組件,context.url指定重定向到的那個路由
也就是說,要是訪問 /,StaticRouter會給我們重定向到/home,并且StaticRouter自動給context對象加了url,context.url就是重定向的/home,當不是重定向時,context.url是undefined
我們還可以自己寫邏輯 通過context來處理302、404等。但這里我不需要。。。。。,為什么呢?
我沒做全棧的同構,只服務端渲染了主頁,渲染一個和多個差不多,全都渲染的話就是在服務端要根據當前請求的路由來決定要發那些請求來填充Store
我對路由的處理流程上面的思維導圖有說明,就是在nginx中多配一個代理。
對于訪問/、/home這兩個路由,代理到ssr服務,來吐首頁內容,api代理到后端服務,其他的直接返回(也就是說如果在detail頁面或user頁面刷新了頁面還是之前客戶端渲染那套)
對登錄操作的處理上面說server端初始化數據的時候還有一個登陸問題沒說。
用戶初始訪問了服務端渲染的首頁,然后在客戶端轉到登錄頁面登陸了,重新回到首頁刷新了頁面,喔,又去請求了ssr服務,但服務端不知道當前用戶登錄了啊,還是原來的流程,返回的__INITIAL_STATE__中還是沒有用戶的個人信息和已登錄狀態
所以,在客戶端登陸后,要將用戶的token存到cookie中,這樣,在首頁就算用戶刷新了頁面,重新請求頁面請求中也會帶上cookie,在服務端,根據request.cookies中是否有token來決定發哪些請求填充store
if (auth) { //要是有token就去查用戶信息和是否登錄狀態(還查是否登錄是因為token有可能是被篡改過的) promises = [ getMoviesList(store, auth), getCategory(store), checkLogin(store, auth), getUinfo(store, auth) ] } else { promises = [ getMoviesList(store), getCategory(store), ] } Promise.all(promises).then(x=>{ renderToString(避免客戶端js中初始請求的觸發) })
到這一步,訪問域名,就能夠正確展示服務端渲染的頁面,跳到別的路由,客戶端的js也能正常處理接下來的事,但是,服務端渲染頁面展示后,首頁那幾個ajax請求還是觸發了,這是沒必要的。
原以為這是react renderToString()生成的標簽和客戶端js hydrate()的有差異導致的,然而,實際上,js執行了,組件的生命周期該觸發還是會觸發的,不只是 attach event listeners to the existing markup
所以要手動避免
在App組件中 componentDidMount() { if (!window.__INITIAL_STATE__) { this.props.checkLogin() this.props.loadCategory() } } //當當前頁面是服務端返回的(因為window.__INITIAL_STATE__有初始狀態),初始的ajax就不觸發了總結
服務端渲染的坑還是挺多的,這一個星期就搞它了。。。。這里記錄一些比較重要的東西,具體細節有興趣的可以看下代碼.最后,最重要的,喜歡的給個star,感謝。。。。。。。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/92464.html
摘要:所以,這次就來聊聊組件的服務器端渲染。這種模式下,后端只提供接口,傳統的服務器端路由模板渲染則都有層接管。這樣,前端開發人員可以自由的決定哪些組件需要在服務器端渲染,哪些組件可以放在客戶端渲染,前后端完全解耦,但又保留了服務器端渲染的功能。 細說 Vue 組件的服務器端渲染 聲明:需要讀者對 NodeJs、Vue 服務器端渲染有一定的了解 現在,前后端分離與客戶端渲染已經成為前端開發的...
摘要:服務端任需要進行校驗來達到數據的可靠性前端的路由可能在服務端并不存在等等這一系列重用性的問題。串行并行,大幅縮短請求時間。關于作者本人主頁本文部分圖片段落參考文章淘寶前后端分離實踐微信公眾號會不定期推送前端技術文章,歡迎關注 一、背景 書接上文,淺談前后端分離與實踐(一) 我們用mock服務器搭建起來了自己的前端數據模擬服務,前后端開發過程中只需定義好接口規范,便可以相互進行各自的開發...
閱讀 1053·2021-11-22 15:33
閱讀 3367·2021-11-08 13:20
閱讀 1379·2021-09-22 10:55
閱讀 2057·2019-08-29 11:08
閱讀 774·2019-08-26 12:24
閱讀 3072·2019-08-23 17:15
閱讀 2233·2019-08-23 16:12
閱讀 1937·2019-08-23 16:09