众所周知,前端三大框架(React, Vue, Angular)的诞生大大解放了前端编写代码的方式,但这三大框架是通过执行js代码生成页面结构的。也正因此带来了一些问题,诸如SEO问题(据说google在爬取页面的时候能够运行js脚本,但其他浏览器还是不支持的),以及首屏加载问题。因此,对于SEO以及首屏渲染性能上有要求的情况下就需要关注一下服务端渲染。

1. 服务端渲染与客户端渲染(SSR & CSR)

服务端渲染

  • 传统WEB开发模式(前后端不分离)

    image-20210106092946568

  • 服务端渲染:浏览器发起页面请求后,有服务端直接生成最终的html文件,然后将html返回给浏览器做展示

  • 自己搭的一个简易服务端渲染

    ​ template.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    </head>
    <body>
    <p>
    <span>username:</span>
    <span style="color: red">{username}</span>
    </p>
    <p>
    <span>age:</span>
    <span>{age}</span>
    </p>
    <p>
    <span>hobby:</span>
    <span>{hobby}</span>
    </p>
    </body>
    </html>

    服务端代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    /**
    核心主逻辑
    **/
    app.get('/detail/:name', (req, res) => {
    // 2. 获取对应的用户名称,获取对应的数据
    const name = req.params.name;
    const user = userlist.find(user => user.username === name);
    if(!user)
    return res.send({ message: 'user information loss, please checkout username....' })
    // 2. 读取模板文件
    readFilePromise('./template.html')
    .then(toString)
    // 3. 模板引擎整合数据与html模板
    .then(templateEngine(user))
    // 4. 服务器返回整合完成的最终的html文件
    .then((html) => res.send(html))
    .catch(errorHandler(res));
    });

客户端渲染

  • React/Vue项目(前后端分离项目)

    image-20210106133411280

SSR & CSR

  • 主要区别:生成html完整的dom结构是在服务端完成还是在客户端完成

    SSR:由后端整合html模板和数据,生成完整的dom结构

    CSR:服务器返回的dom结构不是完整的结构,通过加载js脚本生成完整的dom结构

  • 优缺点对比

    优点 缺点
    客户端渲染 1. 服务端压力小
    2. 便于前后端分离开发
    1. 首屏渲染白屏,主要消耗在js执行生成dom,以及首屏数据需要请求服务器获取,增大了请求数量
    2. SEO,爬虫爬取页面时无法执行js代码,获取不到页面内容
    服务端渲染 1. SEO优化
    2. 首屏渲染块,首屏直接能获得完整dom结构
    1. 服务端需要增加渲染html文件的消耗
    2. 前后端合在一起部署,不容易维护

2. 首屏服务端渲染 + 客户端渲染

react-dom/server $官方文档$

  • renderToString

    1
    2
    3
    // 函数签名
    ReactDOMServer.renderToString:(element:React.Element) => string

    将 React 元素渲染为初始 HTML。React 将返回一个 HTML 字符串。你可以使用此方法在服务端生成 HTML,并在首次请求时将标记下发,以加快页面加载速度,并允许搜索引擎爬取你的页面以达到 SEO 优化的目的。

  • renderToStaticMarkup 是对于renderToString的优化,可以用来渲染纯静态节点

同构(Universal)

  • 是指一套代码可以在服务端和客户端两种环境下运行。

    通过使服务端和客户端运行同一套代码,生成相同的dom结构的方式,通过React的diff算法做到最小化更新,减少客户端渲染开销,达到首屏渲染优化的效果

  • 为什么需要做同构?

    1. 服务端执行代码,主要做的是将React Element转化为html字符串

      但在服务器上是没有dom结构的,因此,无法绑定事件监听,没法执行js代码

      也就是说在服务器端执行完成后得到的是纯静态的html文本

    2. 客户端执行代码,主要是浏览器解析html文件生成dom节点时,为节点绑定事件或者执行特殊功能的js脚本,将纯静态的html文本转化为动态页面

首屏服务端渲染 + 客户端渲染

image-20210107014951176

3. 如何搭建服务端渲染

1w字 | 从零开始的React服务端渲染

代码目录结构

image-20210108002234930
  • client:客户端渲染代码
  • server:服务端渲染代码
  • containers:组件文件夹,前后端公用组件代码
  • common:目前存放的是前后端redux同构代码
  • public:存放客户端build以后的文件
  • build:存放服务端build生成的代码

code:https://github.com/zhangzhengsmiling/react-ssr-demo.git