前一篇主要记录了一下SSR配置以及结合回来的的使用。这里简单说一下SSR反应中样式处理和更优雅的SEO
<强> SSR样式强>
在反应客户端渲染,添加样式很容易。写一个css样式文件,在对应组件中引用。标签上通过className这个属性调用对应样式就万事好了。当然我们需要在webpack中配置加载程序来解析css文件。一般的配置如下(使用css模块):
模块:{ 规则:[{ 测试:/\ . css # 63;美元/, 用途:[style-loader, { 装载机:“css-loader”, 选择:{ importLoader: 1、 模块:没错, localIdentName:“[名字]_(本地)_(散列base64:5): } }) }) } >之前需要先通过css-loader解析css文件,之后再通过style-loader将样式放在html的样式标签中。
那么SSR也这样行吗~
纱线开发 >之前跑一下服务,发现命令行报这个错误:
窗口,返回,文件,,文档。所有的,,! window.atob;
^ReferenceError:窗口没有定义
引用>
原因在于服务器端渲染哪里有窗口对象,哪里有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 模块:{ 规则:[{ 测试:/\ . css # 63;美元/, 用途:[isomorphic-style-loader, { 装载机:“css-loader”, 选择:{ importLoader: 1、 模块:没错, localIdentName:“[名字]_(本地)_(散列base64:5): } }) }) } >之前配置好了运行一下,不报错了但是会闪一下屏。禁用掉js发现服务器端生成的html并没有样式,当客户端js接管程序之后才会有样式出现。这样的体验相当糟糕。
当然我们确实没有向服务器端生成的HTML添加风格标签。
现在服务器返给我们的html是这样的
返回的 & lt; html> & lt; head> & lt; title> ssr & lt;/head> & lt; body> & lt; div id=案痹?{内容}& lt;/div> & lt; script> 窗口。上下文={ 状态:$ {JSON.stringify (store.getState ())} } & lt;/script> & lt;脚本src=" https://www.yisu.com/index.js "祝辞& lt;/script> & lt;/body> & lt;/html> ” >之前这时我们想到了上下文这个玩意。在服务器端渲染之前。我们设置一个
让背景={ css: [] } >之前我们还知道在服务端渲染的时候有<代码> this.props。staticContext 代码>这样一个道具拿到我们设置<代码> 代码>。另外<代码> isomorphic-style-loader> 代码提供给我们了
_getCss()这个方法。可以在SSR过程中拿到样式。有了这两个必要条件。我们就可以在每一个用到样式的组件中通过<代码> componentWillMount 代码>这个生命周期
添加这样一段代码:
componentWillMount () { 如果(this.props.staticContext){//只有服务端渲染时候有this.props.staticContext以及_getCss () this.props.staticContext.css.push (styles._getCss ()) } } >之前这样样式就存储在<代码> 代码>这背景下个变量的css数组中咯,改造一下服务器端html的输出代码:
const cssStr=context.css。长度& # 63;context.css.join (“\ n”):“ 返回的 & lt; html> & lt; head> & lt; title> ssr & lt; style> $ {cssStr} & lt;/style> & lt;/head> & lt; body> & lt; div id=案痹?{内容}& lt;/div> & lt; script> 窗口。上下文={ 状态:$ {JSON.stringify (store.getState ())} } & lt;/script> & lt;脚本src=" https://www.yisu.com/index.js "祝辞& lt;/script> & lt;/body> & lt;/html> ” >之前万事& # 128076;当然我们可以进一步优化,把componentWillMount所做的事情提出来搞一个特别(高阶组件)。
SSR反应样式及SEO的实践