首页 > 开发 > JS > 正文

React SSR样式及SEO的实践

2024-05-06 16:46:33
字体:
来源:转载
供稿:网友

前一篇主要记录了一下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>  `

万事
注:相关教程知识阅读请移步到JavaScript/Ajax教程频道。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表