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.title.toString()} ${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。一个网站无非三大块内容,文字、多媒体、链接。要做到的是文字的原创性,图片的原创性以及高清度还有站内链接尽量和站内内容相关。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 基于React+Redux的SSR实现方法

    为什么要实现服务端渲染(SSR) 总结下来有以下几点: SEO,让搜索引擎更容易读取页面内容 首屏渲染速度更快(重点),无需等待js文件下载执行的过程 代码同构,服务端和客户端可以共享某些代码 今天我们将构建一个使用 Redux 的简单的 React 应用程序,实现服务端渲染(SSR).该示例包括异步数据抓取,这使得任务变得更有趣. 如果您想使用本文中讨论的代码,请查看GitHub: answer518/react-redux-ssr 安装环境 在开始编写应用之前,需要我们先把环境编译/打包环境

  • 使用Node搭建reactSSR服务端渲染架构

    如题:本文所讲架构主要用到技术栈有: Node, Express, React, Mobx, webpack4, ES6, ES7, axios, ejs,  log4js, scss,echarts,ant desige SSR的概念 Server Slide Rendering,缩写为 ssr,即服务器端渲染,因为是后端出身,所以其实早就明白是怎么回事,只是没这个具体名词的概念罢了,这个词被频繁提起也是拜近年来前端飞速发展所赐,主要针对 SPA应用,目的大概有以下几个: 解决单页面应用的 S

  • 详解React+Koa实现服务端渲染(SSR)

    React是目前前端社区最流行的UI库之一,它的基于组件化的开发方式极大地提升了前端开发体验,React通过拆分一个大的应用至一个个小的组件,来使得我们的代码更加的可被重用,以及获得更好的可维护性,等等还有其他很多的优点... 通过React, 我们通常会开发一个单页应用(SPA),单页应用在浏览器端会比传统的网页有更好的用户体验,浏览器一般会拿到一个body为空的html,然后加载script指定的js, 当所有js加载完毕后,开始执行js, 最后再渲染到dom中, 在这个过程中,一般用户只能

  • 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',

  • 简单的React SSR服务器渲染实现

    为什么要SSR 单页应用将UI层和内容都由javascript来渲染,搜索引擎或网页爬虫需要完成的HTML结构,因此单页应用如果只在客户端渲染,不利于SEO,此外尽管我们可以通过按需加载的形式来减少首页加载的js,但是通过js来渲染DOM的时候还是会有一定的时间延迟. 0.前言 服务端渲染在项目中不是刚需的东西,但有的时候也是需要做一个服务端渲染,项目要做服务端渲染当然是有很多好处的 首屏加载快,相比SPA单页应用还要有优势. SEO 优化 利于爬虫,爬取数据. 1. 简介 服务端渲染是指页面的

  • React SSR 中的限流案例详解

    目录 为什么要限流 令牌桶算法 当对 React 应用进行页面加载或 SEO 优化时,我们一般绕不开 React SSR.但 React SSR 毕竟涉及到了服务端,有很多服务端特有的问题需要考虑,而限流就是其中之一. 所谓限流,就是当我们的服务资源有限.处理能力有限时,通过对请求或并发数进行限制从而保障系统正常运行的一种策略.本文会通过一个简单的案例来说明,为什么服务端需要进行限流. 为什么要限流 如下所示是一个简单的 nodejs 服务端项目: const express = require

  • SpringBoot+Mybatis plus+React实现条件选择切换搜索实践

    在写React前端逻辑时,经常遇到可以切换不同条件的列表查询功能,例如下边截图这样的,其实,这块代码基本都一个逻辑,可以一次性将实现过程记录下来,待以后再遇到时,直接根据笔记复用即可. 一.首先,是前端React页面代码,这类搜索框,一般都是放在Form表单当中,然后使用有前缀下拉框选项的Input组件,这类模式的组件是在Input组件当中实现一个addonBefore属性即可,如下代码: render () { let { getFieldDecorator } = this.props.fo

  • React文件名和目录规范最佳实践记录(总结篇)

    目录 文件类型 处理index文件 规范 类型文件夹 特性文件夹 大驼峰命名 烧烤串命名 React在使用时非常灵活,如果没有一个规范约束项目,在开发过程中会非常混乱,本文将介绍几个优秀的规范. 文件类型 介绍文件名和目录前,需要先简述一下几种通用的类型,用来区分文件的功能. component 组件文件 page 如果有路由(React Router.NextJS等),则有页面文件 util 需要复用的工具函数 helper 一段特定逻辑,不是通用工具,可复用也可仅作为代码拆分片段 hook

  • 关于react+antd样式不生效问题的解决方式

    目录 1.添加antd组件样式不生效 2.运行yarn eject时暴露配置文件报错 3.less-loader版本过高,删除旧版本,下载低版本即可 4.项目中引入icon代码报错 补充:React中antd按需加载样式不生效解决办法 总结 1.添加antd组件样式不生效 在入口文件中引入import 'antd/dist/antd.css' 样式生效,但是生成警告 WARNING in ./node_modules/antd/dist/antd.css Failed to parse sour

  • 详解React之key的使用和实践

    在渲染列表时,React的差异比较算法需要一个在列表范围内的唯一key来提高性能(通常用于获知哪个列表项改变了).这个唯一的key需要我们手动提供.React官方建议使用列表数据中可用于唯一性标识的字段来作为列表项渲染时的key.如果实在没有,则可使用数组的index勉为其难,性能上可能会打折扣. 一个例子 有这样的一个场景如下图所示,有一组动态数量的input,可以增加和删除和重新排序,数组元素生成的组件用index作为key的值,例如下图生成的ui展示: 上面例子中的input组件渲染的代码

  • react 应用多入口配置及实践总结

    背景 还是之前的那个项目,做完国际化没多久,还没来得及划水, 又有新的活了 -- 移动端的兼容. 考虑到后期的复杂度, 需要做两套资源. 具体的目标是:同一个URL,PC打开就显示PC的那一套, M端打开就显示Mobile的页面. create-react-app 脚手架本身不支持多入口, 需要改造,今天下午研究了一下,改造了一波, 基本达到了预期, 在这里简单把经验总结分享下. 先睹为快 Mobile: PC: 输出之后的文件, 相比之前的index.html, 多了一个额外的mobile.h

  • 利用React Router4实现的服务端直出渲染(SSR)

    我们已经熟悉React 服务端渲染(SSR)的基本步骤,现在让我们更进一步利用 React RouterV4 实现客户端和服务端的同构.毕竟大多数的应用都需要用到web前端路由器,所以要让SSR能够正常的运行,了解路由器的设置是十分有必要的 基本步骤 路由器配置 前言已经简单的介绍了React SSR,首先我们需要添加ReactRouter4到我们的项目中 $ yarn add react-router-dom # or, using npm $ npm install react-router

随机推荐