富婆來報道,今天想問題想不出來,隨手抓了一下頭髮,沒想到啊沒想到,我那濃(mei)密(sheng)茂(ji)盛(gen)的秀髮又少了好幾根,必定要改掉這個想不出來問題就揪頭髮的壞習慣。大家遇到問題想不出來都會有啥奇特的習慣呢?css
想象一下妙齡美少女長髮飄飄變成三毛的形象(科普:女性禿頂的機率是極低的不會變成英國皇室威廉王子那樣代代傳,可憐新出生的哈里王子的兒子,這個世界上又多了一個禿頭的人),禿頭要怎麼辦呢,只能努力學習掙錢,而後用掉頭髮掙來的錢再去植髮。。。循環。。。html
寫過React組件的同窗都知道,React組件通常是基於瀏覽器端使用js渲染的。它所生成的Dom結構都是後期由js計算生成。以下圖,咱們能夠看到頁面源文件中id爲root中的dom結構實際是空的。但實際在element元素中,已經能夠看到Dom樹的生成了。前端
客戶端渲染DOM結構圖node
服務端渲染DOM結構圖react
簡單瞭解了React-SSR,那麼咱們使用服務端渲染的目的主要是爲了解決以下幾大難題:webpack
一、搜索引擎優化(seo)ios
因React組件採用js在瀏覽器中渲染,實際搜索引擎爬蟲爬到的數據也就是圖一中的沒有DOM結構的數據。,及其不友好,如圖1。git
二、能夠解決首屏白屏問題github
Js渲染的組件須要消耗性能,故在性能較差的終端中,瀏覽器端渲染組件所消耗的時間就會比較長。在瀏覽器執行js渲染組件時,對用戶而言,就是所謂的白屏。web
開啓服務端渲染前
開啓服務端渲染後
開啓先後script計算時間對比
若是你的項目存在上面的問題,而又不想拋棄React組件,能夠嘗試使用React服務端渲染。 服務端渲染,它到底用了什麼原理呢?
服務端渲染的方式有不少,主流的服務端語言爲使用nodejs渲染。下圖爲簡單原理圖:
服務端渲染簡單流程圖
簡單歸納就是這三步驟:
一、客戶端發起請求
二、Nodejs服務器分析頁面數據結構並渲染React組件
三、客戶端展現html
實例解說
下面咱們來看下具體實例,實例是基於express的React服務端組件渲染實例。Express提供頁面以及中間層的API(點擊tab切換調用的接口)服務,Webpack實現服務端和客戶端的React組件打包。
界面預覽
總共包含一個頁面、兩個組件。其中組件1、二均能將首屏數據返回,同時在客戶端從新執行react組件渲染。
首屏DOM結構
實例地址:(這是一個express_react_ssr腳手架) github.com/webqdtalk/e…
運行環境
Nodejs:6.9.0 不限於此版本
Webpack:3.5.2 不限於此版本
Package.json及相關說明
複製代碼
這是Package.json:
{
"name": "react-express-ssr",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "webpack --progress && node ./bin/www"
},
"dependencies": {
"axios": "^0.18.0", //實現組件中ajax請求
"babel-core": "^6.24.0", //打包react組件
"babel-loader": "^6.4.1", //打包react組件
"babel-preset-es2015": "^6.24.0",//打包react組件
"babel-preset-react": "^6.23.0",//打包react組件
"cookie-parser": "~1.4.3", //express依賴
"css-loader": "^0.23.1", //express依賴
"debug": "~2.6.9", //express依賴
"ejs": "~2.5.7", //express依賴
"express": "~4.16.0", //express依賴
"extract-text-webpack-plugin": "^2.1.0",//打包scss文件依賴
"http-errors": "~1.6.2",//express依賴
"morgan": "~1.9.0",//express依賴
"node-sass": "^4.5.1", //打包scss文件依賴
"react": "^16.8.6",//打包react組件
"react-dom": "^16.8.6",//打包react組件,
"sass-loader": "^6.0.3",//打包scss文件依賴
"style-loader": "^0.13.0",//打包scss文件依賴
"webpack": "^3.5.2" //打包react組件
},
"devDependencies": {
"babel-preset-env": "^1.7.0",
"babel-register": "^6.26.0"
}
}
複製代碼
Clone項目後,直接在根目錄執行npm i
安裝完成後運行npm start並打開瀏覽器訪問localhost:3000就能夠訪問了。
重要模塊說明 頁面入口文件配置 當執行npm start並訪問localhost:3000後,express入口文件app.js中引入了server/index.js
App.js
服務端路由如何實現
Express提供router方法
router.get('/urlpath', function(req, res, next) {
const html=ReactDOMServer.renderToStaticMarkup(<App />);
res.render(‘pageejs’, { title:"服務端渲染",content: html });
});
複製代碼
Webpack入口文件:server/index.js中引入了components中的組件,並執行ReactDOMServer.renderToStaticMarkup方法,將組件在服務端渲染爲頁面DOM結構字符串,再由express提供頁面服務,在ejs模板中輸出。
圖四中的兩個api接口是爲了點擊tab時請求數據用。圖五爲ejs模板文件。
Server/index.js
Views/index.ejs
服務端和客戶端如何打包組件? Webpack配置以下:
Webpack.config.js
客戶端渲染的入口文件爲/components/app.js,也包含了服務端的入口文件,保證了服務端和客戶端使用同一套組件輸出,同時也保證在服務端渲染結束後,客戶端組件可以繼續正常運轉。
Components/app.js
以下圖中能夠看到此入口文件中引用了兩個額外的組件:swichtab和ssrplugin,就跟純前端渲染的react組件基本一致!
Components/index.js
實踐過程的注意點
1.express沒法執行import 致使報錯。
解決方案: npm i babel-register --save 同時在bin/www中配置babel-register
require('babel-register')({
presets: ['env']
});
複製代碼
2.服務端渲染css或者scss文件時報錯
解決方案: 因服務端直接運行css或者scss等文件會致使語法報錯,故在實際組件中,須要對require的scss文件進行容錯或者動態按需加載。
try{
require('./index.scss') //因服務端渲染不須要scss文件,但webpack仍會處理scss文件,打包scss會出錯,此處須要做爲容錯處理或按需加載
}catch(e){
console.log(e.message);
}
複製代碼
服務端渲染雖好,可是對項目的改造影響仍是比較大的,改造需謹慎評估~
文章若有不對的地方,歡迎各位斧正!!
歡迎關注個人公衆號,一塊兒禿頭,一塊兒植髮
Web前端Talk