服務(wù)器端渲染主要有兩個(gè)優(yōu)勢(shì)猪勇,一是加快首屏渲染時(shí)間踱承,二是有利于SEO排作。本文將通過圖文簡要分析一下服務(wù)器渲染如何減少首屏渲染時(shí)間。
我們來看看服務(wù)器端與客戶端渲染的流程圖:
圖一為客戶端渲染流程圖油吭,圖二击蹲,三為服務(wù)器端渲染流程圖。
兩個(gè)渲染圖都可以分為兩個(gè)階段:
一:客戶端發(fā)送請(qǐng)求婉宰,服務(wù)器端返回html文件歌豺。
二:客戶端請(qǐng)求js文件,下載完成后本地建立react實(shí)例心包。
盡管服務(wù)器渲染第一階段的流程圖很長类咧,但是因?yàn)榉?wù)器渲染速度很快,因此實(shí)際耗時(shí)與客戶端渲染幾乎相同蟹腾。
第一階段結(jié)束時(shí)痕惋,服務(wù)器端返回渲染結(jié)果,用戶即可看到首屏娃殖。而對(duì)于客戶端渲染值戳,需要等待一次腳本下載時(shí)間,以及在客戶端的渲染時(shí)間炉爆。由于客戶端的硬件以及網(wǎng)絡(luò)條件的差異堕虹,這兩段時(shí)間開銷可能十分顯著。
客戶渲染與服務(wù)器渲染第二階段基本一致芬首。所不同的是赴捞,服務(wù)器渲染流程中,在客戶端生成vdom后郁稍,并不會(huì)重新渲染赦政,而是比較現(xiàn)有dom的checksum來決定是否重新渲染。
實(shí)戰(zhàn)中的服務(wù)器端渲染需要配置很多問題耀怜,比如說:
- 如何保持前后端數(shù)據(jù)一致
- 如何在后端進(jìn)行路由恢着,且和前端共享路由代碼
- 服務(wù)器端如何打包靜態(tài)資源
前后端數(shù)據(jù)一致
我們假設(shè)使用redux作為store。在服務(wù)器渲染時(shí)财破,將store傳入渲染函數(shù)然评,隨后將store作為全局變量插入到返回的html文件中。
在客戶端文件中狈究,使用該全局變量作為store的初始值。代碼片段如下:
//server side
var root = renderToString(
<Provider store={store}>
<RouterContext {..._renderProps}/>
</Provider>
)
ctx.render('home', {
root,
state: store.getState()
})
//view template
script.
window.REDUX_STATE = !{JSON.stringify(state)}
//client side
const store = configureStore(window.REDUX_STATE);
路由控制
首先將具體的路由提取到單一文件中。
const routes = (
<Route path="/" component={NavBar}>
<IndexRoute component={App} />
<Route path="/Person" component={Person} />
<Route path="/Profile" component={Profile} />
</Route>
)
隨后在客戶端與服務(wù)器端:
//客戶端
<Provider store={store}>
<Router history={browserHistory}>
{routes}
</Router>
</Provider>
//服務(wù)器
match({routes, location: ctx.url}, (error, redirectLocation, renderProps) => {
_renderProps = renderProps
});
<Provider store={store}>
<RouterContext {..._renderProps}/>
</Provider>
這里match抖锥,RouterContext都是react-router為了服務(wù)器渲染準(zhǔn)備的函數(shù)亿眠。
服務(wù)器端如何打包靜態(tài)資源
這個(gè)沒什么經(jīng)驗(yàn)。
大家可以看看這篇文章http://www.reibang.com/p/0ecd727107bb磅废。 我的這篇文章主要是根據(jù)ChikaraChan的文章寫的學(xué)習(xí)筆記纳像。
ChikaraChan為服務(wù)器端渲染寫了一個(gè)腳手架。除了我剛剛提到的幾個(gè)問題拯勉,他還考慮開發(fā)項(xiàng)目的其他很多問題竟趾。
參考文章