React SSR样式及SEO的实践
前一篇主要记录了一下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)– 通过一些技术手段让网站在搜索引擎的排名尽量靠前一点。由于客户端渲染出来的网站只有<div id='root'>这样的html节点。大多数搜索引擎分析不出来网站上有什么。SSR直接渲染出来HTML,这样对搜索引擎就友好了很多。
SSR中的SEO
这里我们使用github上的一个库react-helmet首先需要在对应的页面组件中引入react-helmet,就可以在Helmet标签内自由添加title、meta咯
// Home.jax import { Helmet } from 'react-helmet' class Home extends Component { render() { return ( <Fragment> <Helmet> <title>SRR-Home</title> <meta name='description' content='this is a home Component' /> </Helmet> ... ... </<Fragment>> ) } }
之后按照readme所说的。在server端这样处理
ReactDOMServer.renderToString(<Handler />); const helmet = Helmet.renderStatic();
并在返回的html字符串中 {helmet.meta.toString()}进行填充
<html> <head> ${helmet.title.toString()} ${helmet.meta.toString()} <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>
重新跑一下 搞定!
当然SSR-SEO绝不这么简单。仅仅在页面上添加head标签内加上title 和meta标签影响是有限的。8102年的搜索爬虫已经不单单去匹配title和 description,而是全稳的匹配(也就是说title和descript有影响但是影响很小)搜索爬虫会把整个网站所有的文本收集起来进行分析。
那么如何做好SEO
题外话顺便说一下如何做好SEO。一个网站无非三大块内容,文字、多媒体、链接。要做到的是文字的原创性,图片的原创性以及高清度还有站内链接尽量和站内内容相关。
为了学习工作与休闲娱乐互不冲突,现新建圈【码农茶水铺】用于程序员生活,爱好,交友,求职招聘,吐槽等话题交流,希望各位大神工作之余到茶水铺来喝茶聊天。了解更多
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
React Native工程中TSLint静态检查工具的探索之路
背景 建立的代码规范没人遵守,项目中遍地风格迥异的代码,你会不会抓狂? 通过测试用例的程序还会出现Bug,而原因仅仅是自己犯下的低级错误,你会不会抓狂? 某种代码写法存在问题导致崩溃时,只能全工程检查代码,这需要人工花费大量时间Review代码,你会不会抓狂? 以上这些问题,可以通过静态检查有效地缓解! 静态检查(Static Program Analysis)主要是以不运行程序的方式对于程序源代码进行检查分析的技术,而与之相反的就是动态检查(Dynamic Program Analysis),通过实际运行程序输入测试数据产生预期结果的技术。通过代码静态检查,我们可以快速定位代码的错误与缺陷,可以减少逐行阅读代码浪费的时间,可以(根据需要)快速扫描代码中可能存在的漏洞等。代码静态检查可以在代码的规范性、安全性、可靠性、可维护性等方面起到重要作用。 在客户端中,Android可以使用CheckStyle、Lint、Findbugs、PMD等工具,iOS可以使用Clang Static Analyzer、OCLint等工具。而在React Native的开发过程中,针对于JavaScrip...
- 下一篇
iOS开发之CoreMotion框架的应用
iOS开发之CoreMotion框架的应用 我们知道,现在智能手机手机的功能已经越来越强大。小小的手机中集成了众多的传感器配件。通过这些传感器可以获取到手机甚至用户的状态信息。 在iOS5之前,加速度传感器的相关信息封装在UIAccelerometer这个类中,其主要用来获取设备在三维空间中的状态信息,之后,加速度传感器以及螺旋仪传感器的相关信息都封装在了CoreMotion这个框架中,这个框架对加速度,磁力以及螺旋仪传感器信息进行统一管理,并封装了许多强大的计算方法帮助开发者获取设备的空间状态。 之前有写过一篇关于UIAccelerometer与CoreMotion简单使用的博客,比较偏用法介绍,并不系统,本篇博客是针对CoreMotion的完善与补充。 https://my.oschina.net/u/2340880/blog/543434 一、CoreMotion框架整体结构 在学习这个框架之前,首先需要对框架中类的关系与作用有个整体的了解。下图展示了CoreMotion框架的整体结构: 从上图中可以看出,CoreMotion框架中主要分为3大块,一部分是用...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS关闭SELinux安全模块
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Windows10,CentOS7,CentOS8安装Nodejs环境
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- SpringBoot2整合Redis,开启缓存,提高访问速度
- SpringBoot2更换Tomcat为Jetty,小型站点的福音