大家好,今天給大家帶來一篇關於react服務端渲染的文章。

那麼什麼是react服務端渲染呢?

我們來看看。

React服務端渲染

寫過React組件的同學都知道,React組件一般是基於瀏覽器端使用js渲染的。它所生成的Dom結構都是後期由js計算生成。如下圖,我們可以看到頁面源文件中id為root中的dom結構實際是空的。但實際在element元素中,已經可以看到Dom樹的生成了。

圖1:客戶端渲染DOM結構圖

圖2:服務端渲染DOM結構圖

React服務端渲染(簡稱SSR),也就是在伺服器端直接渲染React組件,使用戶在首屏便能感受到Dom樹的存在,在頁面html文件生成的同時,Dom結構也就存在了。用戶看到的源文件即為圖2。

那麼為什麼要使用服務端渲染呢?客戶端渲染不是更能減輕服務端負擔嗎?

我們來看下

為什麼要使用服務端渲染

簡單瞭解了React-SSR,那麼我們使用服務端渲染的目的主要是為瞭解決如下幾大難題:

搜索引擎優化(seo)

因React組件採用js在瀏覽器中渲染,實際搜索引擎爬蟲爬到的數據也就是圖一中的沒有DOM結構的數據。,及其不友好,如圖1。

可以解決首屏白屏問題

Js渲染的組件需要消耗性能,故在性能較差的終端中,瀏覽器端渲染組件所消耗的時間就會比較長。在瀏覽器執行js渲染組件時,對用戶而言,就是所謂的白屏。

圖3:開啟服務端渲染前

圖4:開啟服務端渲染後

圖5:開啟前後script計算時間對比

如果你的項目存在上面的問題,而又不想拋棄React組件,可以嘗試使用React服務端渲染。

服務端渲染,它到底用了什麼原理呢?

服務端渲染原理

服務端渲染的方式有很多,主流的服務端語言為使用nodejs渲染。圖六為簡單原理圖:

圖6:服務端渲染簡單流程圖

簡單概括就是這三步驟:

  1. 客戶端發起請求
  2. Nodejs伺服器分析頁面數據結構並渲染React組件
  3. 客戶端展示html

實例解說

下面我們來看下具體實例,實例是基於express的React服務端組件渲染實例。Express提供頁面以及中間層的API(點擊tab切換調用的介面)服務,Webpack實現服務端和客戶端的React組件打包。

界面預覽

總共包含一個頁面、兩個組件。其中組件一、二均能將首屏數據返回,同時在客戶端重新執行react組件渲染。

首屏DOM結構

實例地址:(這是一個express_react_ssr腳手架)

github.com/webqdtalk/ex

運行環境

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

服務端渲染的入口文件為components/index.js,如下圖中可以看到此入口文件中引用了兩個額外的組件:swichtab和ssrplugin,就跟純前端渲染的react組件基本一致!

Components/index.js

客戶端打包組件後輸出在public/main.css和public/index.js,在視圖文件views/index.ejs中引用實現客戶端渲染。

實踐過程的注意點

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);

}

服務端渲染雖好,但是對項目的改造影響還是比較大的,改造需謹慎評估~

你懂的!!!


推薦閱讀:
相關文章