React服務(wù)端渲染原理
由于React是通過動(dòng)態(tài)Dom樹進(jìn)行HTML的繪制偎快,并且是數(shù)據(jù)驅(qū)動(dòng)視圖的蛇捌,所以在SEO的搜索中百姓,動(dòng)態(tài)Dom樹的填充內(nèi)容不會(huì)被搜索到笛洛。當(dāng)網(wǎng)頁(yè)需要提高搜索量,或者進(jìn)行某些兼容性處理時(shí)咐蚯,就需要將動(dòng)態(tài)的Dom樹轉(zhuǎn)換為字符串的形式以靜態(tài)資源進(jìn)行加載童漩,兼容性的處理也是通過對(duì)靜態(tài)資源根據(jù)瀏覽器不通特性,通過Hack等規(guī)則替換進(jìn)行實(shí)現(xiàn)春锋。(剛查看了資料矫膨,可以將字符串的Dom轉(zhuǎn)換為XML進(jìn)行替換:使用工具:var xmlDoc = new ActiveXObject(/"Microsoft.XMLDOM/");)。
服務(wù)端渲染的實(shí)現(xiàn)期奔,是通過開啟nodejs服務(wù)監(jiān)聽侧馅,將已經(jīng)渲染好的Dom頁(yè)面加載到瀏覽器端進(jìn)行展現(xiàn);
當(dāng)使用服務(wù)器端渲染時(shí)呐萌,如果需要使用Redux馁痴,則將store賦值給Provider在Router中進(jìn)行store的傳遞;
import { StaticRouter, RouterContext } from 'react-router';
import { Provider } from 'react-redux';
<Provider store={finalState}>
<StaticRouter location={req.url} context={context}>
{getRoutes()}
</StaticRouter>
</Provider>
當(dāng)需要使用Router中 history時(shí)肺孤,需要將組件包裹在 withRouter 中
import { withRouter } from 'react-router';
export default connect(mapStateToProps,mapDispatchToProps)(withRouter(AgencyEvent));
當(dāng)nodejs服務(wù)監(jiān)聽到訪問請(qǐng)求時(shí)罗晕,通過${}EL 表達(dá)式,將繪制好的Dom頁(yè)面以字符串的形式寫入到html模版中赠堵,使用response渲染到瀏覽器端進(jìn)行展示小渊。此時(shí)渲染出的html頁(yè)面是沒有攜帶事件機(jī)制的。所以此時(shí)需要再次在客戶端進(jìn)行渲染茫叭,使得DOM樹的節(jié)點(diǎn)可以觸發(fā)酬屉。
React服務(wù)端渲染實(shí)現(xiàn)
import { renderToString } from 'react-dom/server';
const markup = renderToString(
<Provider store={finalState}>
<StaticRouter location={req.url} context={context}>
{getRoutes()}
</StaticRouter>
</Provider>
);
const html = renderPage (markup, {});
res.status(200).send(html);
function renderPage (html, initialState) {
return `
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>服務(wù)端渲染頁(yè)面</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root">${html}</div>
<script>
window.__INITIAL_STATE__ = ${JSON.stringify(initialState)}
</script>
<script type="text/javascript" src="/static/bundle.js" defer></script>
</body>
</html>`;
如果模版不需要進(jìn)行特別處理,也可以使用webpack自動(dòng)生產(chǎn)的html文件進(jìn)行渲染
參考地址:
https://reacttraining.com/react-router/web/guides/server-rendering
https://redux.js.org/recipes/server-rendering