国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

React SSR樣式及SEO的實踐

2019-11-19 12:39:05
字體:
來源:轉載
供稿:網友

前一篇主要記錄了一下SSR配置以及結合Redux的使用。這里簡單說一下React SSR中樣式處理和更優雅的SEO

SSR樣式

在React客戶端渲染,添加樣式很容易。寫一個css樣式文件,在對應組件中引用。標簽上通過className這個屬性調用對應樣式就萬事Ok了。當然我們需要在webpack中配置loader來解析css文件。一般的配置如下(使用css modules):

module: { rules: [{  test: //.css?$/,  use: ['style-loader', {   loader: 'css-loader',   options: {    importLoader: 1,    modules: true,    localIdentName: '[name]_[local]_[hash:base64:5]'   }  }] }]}

需要先通過css-loader解析css文件,之后再通過style-loader將樣式放在html的style標簽中。

那么SSR也這樣行嗎~

yarn dev

跑一下服務,發現命令行報這個錯誤:

return window && document && document.all && !window.atob;
^

ReferenceError: window is not defined

原因在于服務器端渲染哪里有window對象,哪里有DOM啊。我們是通過虛擬DOM。renderToString這個方法生成出來的html字符串。stackoverflow搜了一下發現了isomorphic-style-loader這個專門用于同構的style-loader。

話不多少搞起來。客戶端的webpack配置不需要變更還是使用css-loader+style-loader。服務器端就使用css-loader+isomorphic-style-loader了(和style-loader用法一波一樣)

// webpack.server.js module: {  rules: [{   test: //.css?$/,   use: ['isomorphic-style-loader', {    loader: 'css-loader',    options: {     importLoader: 1,     modules: true,     localIdentName: '[name]_[local]_[hash:base64:5]'    }   }]  }] }

配置好了Run一下,不報錯了但是會閃一下屏。禁用掉js發現server端生成的html并沒有樣式,當客戶端JS接管程序之后才會有樣式出現。這樣的體驗相當糟糕。

當然我們確實沒有向服務器端生成的HTML添加style標簽。

現在服務器返給我們的html是這樣的

return `  <html>   <head>    <title>ssr</title>   </head>   <body>    <div id='root' >${ content }</div>    <script>     window.context = {      state: ${ JSON.stringify(store.getState()) }     }    </script>    <script src='/index.js' ></script>   </body>  </html> `

這時我們想到了context這個玩意。在server端render之前。我們設置一個

let context = { css: []}

我們還知道在服務端渲染的時候有this.props.staticContext這樣一個props拿到我們設置context。另外isomorphic-style-loader提供給我們了

_getCss()這個方法。可以在SSR過程中拿到樣式。有了這兩個必要條件。我們就可以在每一個用到樣式的Component中通過componentWillMount這個生命周期

添加這樣一段代碼:

componentWillMount () { if (this.props.staticContext) { // 只有服務端渲染時候有this.props.staticContext以及_getCss()  this.props.staticContext.css.push(styles._getCss()) }}

這樣樣式就存儲在context這個變量的css數組中咯,改造一下server端的html輸出代碼:

const cssStr = context.css.length ? context.css.join('/n') : '' return `   <html>    <head>     <title>ssr</title>     <style>${cssStr}</style>    </head>    <body>     <div id='root' >${content}</div>     <script>      window.context = {       state: ${JSON.stringify(store.getState())}      }     </script>     <script src='/index.js' ></script>    </body>   </html>  `

萬事👌,當然我們可以進一步優化,把componentWillMount所做的事情提出來搞一個HOC(高階組件)。

withStylesHOC.js

import React, { Component} from 'react'export default (DecoratedComponent, styles) => { return class NewComponent extends Component {  componentWillMount () {   if (this.props.staticContext) {    this.props.staticContext.css.push(styles._getCss())   }  }  render () {   return <DecoratedComponent {...this.props} />  } }}

這樣簡單的封裝一個HOC,之后涉及樣式的時候直接通過withStylesHOC包裹一下就好。例如一個結合Redux的Home組件:

export default connect(mapState, mapDispatch)(withStyle(Home, styles))

SSR-SEO

費大力氣通過一個node中間層去實現首屏的SSR,除開首屏速度之外,就是SEO這一大塊了,對于一個商業網站來講真的很重要。

SEO(Search Engine Optimization)

主站蜘蛛池模板: 元朗区| 金平| 正定县| 武平县| 江西省| 柘城县| 广元市| 三门峡市| 如东县| 栖霞市| 米脂县| 区。| 镇巴县| 民丰县| 洪泽县| 鹰潭市| 彩票| 石河子市| 会泽县| 宁津县| 抚顺县| 泽库县| 信丰县| 兴业县| 邢台县| 奉贤区| 平邑县| 扶沟县| 错那县| 阿图什市| 西畴县| 泽州县| 山西省| 永新县| 乌恰县| 隆昌县| 嘉荫县| 宜阳县| 辽阳县| 东丰县| 平潭县|