導(dǎo)語: 本文面向沒用過服務(wù)端渲染以及沒了解過的同學(xué)闷营。主要介紹了服務(wù)端渲染的歷史成翩,以及React.js興起以后的同構(gòu)渲染,并分別給出了React.js和Vue.js 的SSR(Server Side Render)的同構(gòu)例子盗飒。所有代碼在github中給出烈拒,可以直接運行圆裕。
服務(wù)端渲染其實在10多年前Asp, Java就流行了,那個時候都是通過一個后端的模版實現(xiàn)荆几。后來出現(xiàn)了jQuery等庫和框架之后吓妆,各種動態(tài)頁面又由后端渲染變成了客戶端渲染。2013年React.js的出現(xiàn)后吨铸,同構(gòu)渲染頁面的思想慢慢的流行起來行拢。 所謂同構(gòu)渲染就是相同的組件既可以在服務(wù)端中渲染也可以在前端渲染。能滿足這個條件的服務(wù)端只有node.js诞吱。本文主要是講同構(gòu)渲染,也叫做node直出狐胎。
雖然同構(gòu)的思想出現(xiàn)了三年多,但前段時間在面試過程中問了不了社招和校招的同學(xué)握巢,對這個概念很多同學(xué)都不太清楚松却,或者是實踐非常少。原因可能是大家所在公司使用node服務(wù)的比較少晓锻。沒有很好的實踐平臺。 下面就把這個問題講清楚吧砚哆。
先說幾個同構(gòu)渲染的好處:
?1. 首屏性能相比提升非常多。
?2. node服務(wù)和前端公用一套代碼
?3. SEO, 對搜索引擎友好
?4. 互聯(lián)網(wǎng)公司面試題常出
沒有同構(gòu)渲染,頁面的首屏?xí)r間卵史,
對比上面兩個圖, 可以發(fā)現(xiàn)SSR最少省了兩次從客戶端請求到服務(wù)端的時間啄踊,一次請求的來回我們叫做RTT時間(Round-Trip Time),特別是在移動端在3G請求一次RTT時間需要500ms颠通,4G和wifi是100ms。 所以從這里可以看出服務(wù)端渲染在首屏?xí)r間上有很大的優(yōu)化顿锰。如果在返回的html中內(nèi)聯(lián)首屏的Css樣式,那么用戶發(fā)起html的一次請求就可以看到首屏的頁面撵儿。 是的,只要一個請求淀歇。本文并不是專門講性能優(yōu)化,所以這里簡單總結(jié)浪默,通常SSR可以讓首屏?xí)r間節(jié)省大概1.5s到2s。像React.js這種150kb左右(React 16大約106kb), 也不會影響首屏?xí)r間纳决。
這里的dom string就是React.js或者Vue.js提供的方法, 根據(jù)數(shù)據(jù)生成的類似于<div></div>的字符串。 實踐起來非常簡單阔加,只需要在node服務(wù)調(diào)用一個方法就可以生成。當(dāng)然這里需要使用node服務(wù)作為中間層胜榔,node服務(wù)的好處就不在這里說了。
下面就挑React.js和Vue.js作為例子夭织,大家可以直接跳到自己常用的框架看對應(yīng)的例子即可,
以React為例尊惰,node服務(wù)中路由收到請求時泥兰,利用React提供的renderToString方法對組件IndexPage輸出字符串body,
router.use('/index.html', function (req, res, next) {
let body = ReactDOMServer.renderToString(<IndexPage />);
console.log(body);
res.render("page", {
body: body
});
});
indexPage組件如下题禀,
import React from 'react';
class App extends React.Component {
render() {
return (
<div>
hello React SSR!
</div>
);
}
}
export default App;
domString的輸出結(jié)果是
<div data-reactroot="" data-reactid="1" data-react-
checksum="-1619127114">hello React SSR!</div>
再把domString插入到模版中返回給瀏覽器就完成node直出了。
完整的代碼在這里: https://github.com/blogExample2010/blog/tree/master/ReactSSR
參考Readme.md就可以一步步跑起來投剥。
同樣以Vue.js為例, 官方文檔 https://ssr.vuejs.org/zh/basic.html江锨,利用vue-server-renderer的renderToString方法生成字符串插入到模版中。
const renderer = require('vue-server-renderer').createRenderer()
router.use('/index.html', function (req, res, next) {
renderer.renderToString(IndexPage, (err, body) => {
if (err) throw err
console.log(body)
res.render("page", {
body: body
});
})
});
body在控制臺輸出:
<div data-server-rendered="true">Hello Vue SSR!</div>
完整的代碼在這里: https://github.com/blogExample2010/blog/tree/master/VueSSR
總結(jié)酌心,其實同構(gòu)渲染一點也不復(fù)雜,參考上面的代碼相信完全可以把這部分掌握起來安券。 node直出對提升首屏性能還是非常明顯的變化。