web性能优化之SSR同构渲染

web性能优化之SSR同构渲染

2020年01月15日 阅读:5 字数:914 阅读时长:3 分钟

在需要首屏渲染速度优化的场景下,大家或多或少都听到过服务端同构渲染,本站也使用到了,仅以此文记录下当时查阅的资料。

在需要首屏渲染速度优化的场景下,大家或多或少都听到过服务端同构渲染,本站也使用到了,仅以此文记录下当时查阅的资料。

首先看下web页面渲染的历史:服务端渲染 -> 客户端渲染 -> 服务端同构渲染(Server Side Render)

服务端渲染

其实早期的 Web页面渲染都是在服务端进行的,服务端渲染步骤:

  1. 客户端发请求
  2. 服务端查询数据库取数据
  3. 服务端将数据和模板渲染为完整 HTML
  4. 服务端发送给客户端
  5. 客户端接收直接展示

以JSP开发技术为例:

3581a715827b021a.png

然而,在网页越来越复杂的情况下,这种方式存在很多不足:

  • 前后端代码完全耦合在一起,不利于开发和维护
  • 前端没有足够发挥空间(前端只单纯展示)
  • 服务端压力大
  • 用户体验一般(每次查看新页面要刷新,而spa不需要刷新)

客户端渲染

说到渲染方式,我们普遍使用最多的就是基于客户端渲染前端框架,例如 Angular,React,Vue 等。使用它们开发 SPA 单页面应用时,具有如下优缺点:

优点

  • 用户体验好
  • 开发效率高
  • 渲染性能好
  • 可维护性好

缺点

  • 首屏渲染时间长
  • 不利于 SEO

同构渲染

首先什么是同构?:一套代码运行在Node服务端又运行在客户端。

服务端同构渲染 SSR (Server-Side Rendering),是指在服务端完成页面的html 拼接处理, 然后再发送给浏览器,将不具有交互能力的html结构绑定事件和状态,在客户端展示为具有完整交互能力的应用程序。

d5f84f6c82756e39.png

基于React、Vue等框架,客户端渲染 和 服务器端渲染 的结合,核心解决 SEO 和 首屏渲染 慢的问题。

  • 在服务器端执行一次,用于实现服务器端渲染(首屏直出)
  • 在客户端再执行一次,用于接管页面交互
  • 拥有传统服务端渲染的优点,也有客户端渲染的优点

不过也要注意几个问题

  • 同构资源的处理,拿Vue来说能在服务器端中调用的生命周期只有beforeCreatecreated,操作DOM、Window、Document对象或者使用三方 API 时必须保证运行不报错。
  • 需要Node.js Server环境,可以外面套一层Nginx
  • 需要考虑更多的缓存问题,应用代码需在双端运行解析,cpu 性能消耗更大,负载均衡和多场景缓存处理比 SPA 做更多准备。

怎么实现?

目前前端流行的三种技术栈 React, Vue 和 Angular ,已经孵化出对应的服务端渲染框架,开箱即用。

React: Next.js

Vue: Nuxt.js

Angular: Nest.js

拿本站为例,使用的是Nuxt.js,作为Node.js中间件使用Renderer处理和服务所有 SSR 和资源请求,开发环境先Builder然后再渲染,生产环境直接使用nuxt build构建好的资源进行渲染。

const { Nuxt, Builder } = require('nuxt');

module.exports = options => {
  const config = require('config/nuxt.front.js'));
  config.dev = options.isDev;

  const nuxt = new Nuxt(config);

  if (options.isDev) {
    new Builder(nuxt).build();
  }

  const middleware = async(ctx, next) => {
    // Default 404
    ctx.status = options.status || 200;
    ctx.req.session = await ctx.session();
    await nuxt.render(ctx.req, ctx.res);

    let err = null;
    return next().catch(e => {
      err = e;
    }).then(() => {
      if (err) {
        return Promise.reject(err);
      }
      // 如果后续执行逻辑有错误,则将错误返回
      return new Promise((resolve, reject) => {
        return { resolve, reject };
      });
    });
  };
  return middleware;
};

具体参考:Node.js从零开发博客(一)框架搭建

推荐阅读

恰饭区

评论区 (0)

0/500

还没有评论,快来抢第一吧