服务端渲染

359 阅读3分钟

传统的服务端渲染

早期的web页面渲染都是在服务端进行的
一个简单的例子,node端读取一个页面的html并嵌入数据,最后将页面返回给前端

const express = require('express')
const fs = require('fs')
const template = require('art-template')
const app = express()
app.get('/', (req, res) => {
    // 1、获取页面模板
    const tpl = fs.readFileSync('./index.html', 'utf-8')
    // 2、获取数据
    const data = JSON.parse(fs.readFileSync('./data.json', 'utf-8'))
    // 3、执行渲染
    const html = template.render(tpl, data)
    // 4、把渲染完的页面发送给客户端
    res.send(html)
})
app.listen(3000, () => console.log('running...'))

最终页面展示的是data.json中的数据,前端请求的接口返回的数据就是已经处理好的html代码,如股应用不复杂的情况下,这种方式是完全可取的
但是如果在复杂情况下,这种方式会存在很多不足:

  • 前端端代码完全耦合在一起,不利于开发和维护
  • 前端没有足够的发挥空间
  • 服务端压力比较大
  • 用户体验一般,跳转其他页面需要重新刷新

客户端渲染

Ajax的出现使得客户端动态获取数据成为可能。
原本在服务端的工作转移到了客户端。此时后端负责处理数据接口,前端负责将数据渲染到页面中,更为独立,不再受限制于后端
但这样也存在一些明显的不足:

  • 首屏渲染慢
  • 不利于SEO

为什么客户端渲染首屏渲染时间长?

以Vue SPA项目为例,加载一个页面首先要请求静态页面,其次请求页面中的js脚本,最后如果有ajax的话执行ajax,这三部分并不是同时进行的,但是服务端渲染只进行一次请求,直接拿到已经编译好的html静态内容,所以首屏渲染时服务端渲染会比客户端快。

为什么客户端渲染不利于SEO?

搜索引擎请求各个网址,拿到返回的静态html字符串,根据字符串的内容进行分析、收录、排名等操作。如果是服务端渲染(SSR),搜索引擎拿到的是已经插入数据之后的html字符串,即所见即所得,有利于网站的排名,但是客户端渲染(CSR)的页面,以Vue SPA项目为例,搜索引擎拿到的就只是一个带有<div id="app"></div>的html字符串,并不会加载其中的静态资源,内容是空的,SEO自然无从谈起。

现在化的服务端渲染(同构渲染)

同构渲染=后端渲染+前端渲染
基本流程:

  • 基于React、Vue等框架,客户端渲染和服务器端渲染的结合
    • 在服务端执行一次,用于实现服务端渲染(首屏直出)
    • 在客户端再执行一次,用于接管页面交互
  • 核心在于解决SEO和首屏渲染慢的问题
  • 拥有传统服务端渲染的优点,也有客户端渲染的优点 如何实现:
  • 使用Vue、React等框架的官方解决方案
    • 优点:有助于理解原理
    • 缺点:需要搭建环境,比较麻烦
  • 使用第三方解决方案
    • React生态的Next.js
    • Vue生态的Nuxt.js
    • ...

同构渲染应用的问题

  • 开发条件有限
    • 浏览器中特定的代码只能在某些生命周期钩子函数中使用
    • 一些外部扩展库可能需要特殊处理才能在服务端渲染应用中运行
    • 不能在服务端渲染期间操作DOM
    • 某些代码操作需要区分运行环境
  • 涉及构建和部署的要求会更多,同构渲染应用只能部署在Node.js Server
  • 更多的服务端渲染优化工作处理,如果流量比较高,需要做服务器负载的一些工作

服务端渲染的建议

  • 首屏渲染速度是否真的重要
  • 是否真的需要SEO

以Vue生态的Nuxt.js为例演示同构渲染应用

ssr-demo