生活就是个缓慢受锤的过程
人一天天老下去
奢望也一天天消失
最后变得像挨了锤的牛一样
一、概述
1. 客户端渲染
客户端渲染的前端框架: Angular、React、Vue
SPA单页应用:
优点: 用户体验好、开发效率高、渲染性能好、可维护性好
缺点: 首屏渲染时间长、不利于SEO
2. 现代化的服务端渲染
服务器渲染流程:
客户端激活为SPA: 为了获得更好的用户体验,同时会在客户端将来自服务端渲染的内容激活为一个 SPA应用
3. 同构应用
- 通过服务端渲染首屏,解决SPA应用首屏渲染慢,以及不利于SEO问题
- 通过客户端渲染结果页面,内容交互得到更好的用户体验
- 这种方式通常称之为现代化的服务端渲染,也叫同构渲染
- 这种方式构建的应用称之为服务端渲染应用或者是同构应用
4. 什么是渲染
渲染: 把数据和模板拼接在一起。渲染的本质就是字符串的解析替换。
二、传统的服务端渲染
1. 服务端渲染流程
早期时候,Web 页面渲染都是在服务端完成的,服务端将所需的数据结合页面模板渲染为HTML,响应给客户端浏览器。
首先,客户端发起一个请求,服务端收到请求后,获取对应的数据,然后把数据结合页面模板渲染为完整的 HTML,接着把渲染完毕的 HTML 发送给客户端,客户端接收到内容将其直接展示到浏览器当中。
2. Node.js 演示
⑴. 基础代码
data.json: 模拟数据库存储的数据
{
"posts": [
{
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
},
{
"id": 2,
"title": "qui est esse",
"body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
},
{
"id": 3,
"title": "ea molestias quasi exercitationem repellat qui ipsa sit aut",
"body": "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut"
},
{
"id": 4,
"title": "eum et est occaecati",
"body": "ullam et saepe reiciendis voluptatem adipisci\nsit amet autem assumenda provident rerum culpa\nquis hic commodi nesciunt rem tenetur doloremque ipsam iure\nquis sunt voluptatem rerum illo velit"
},
{
"id": 5,
"title": "nesciunt quas odio",
"body": "repudiandae veniam quaerat sunt sed\nalias aut fugiat sit autem sed est\nvoluptatem omnis possimus esse voluptatibus quis\nest aut tenetur dolor neque"
}
],
"title": "文档标题"
}
index.html: 网页入口文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>传统的服务端渲染</title>
</head>
<body>
<h1>传统的服务端渲染</h1>
<h2>{{ title }}</h2>
<ul>
{{ each posts }}
<li>{{ $value.title }}</li>
{{ /each }}
</ul>
</body>
</html>
⑵. 安装依赖
# 创建 http 服务
npm i express
# 服务端模板引擎
npm i art-template express-art-template
⑶. 创建后端服务文件
// index.js
const express = require('express')
const fs = require('fs')
const template = require('art-template')
// 创建一个 express 实例
const app = express()
// 添加一个路由,当其以get请求网站根路径时触发
app.get('/', (req, res) => {
// 1. 获取页面模板,node中需要先读取文件,然后就可以将该文件保存到一个变量中
// 读取文件的方法常用的有两种,readFile 是一个异步方法,readFileSync 是一个同步方法
// 默认得到的是Buffer二进制数据,为了得到字符串HTML模板可以指定utf-8编码
const templateStr = fs.readFileSync('./index.html', 'utf-8')
// 2. 获取数据
// 注意,采用这种读取方法读取到的返回结构都是字符串,使用JSON.parse()转换成数据对象
const data = JSON.parse(fs.readFileSync('./data.json', 'utf-8'))
// 3. 渲染:数据 + 模板 = 最终结果
// 使用art-template模板引擎,模板引擎的本质就是对字符串进行解析替换
// 第一个参数:要渲染的模板字符串
// 第二个参数:数据对象
// 如:
// template.render('hello {{message}}', {message: 'world'} )返回结果是hello world
const html = template.render(templateStr, data)
// 4. 把渲染结果发送给客户端
res.send(html)
})
app.listen(3000, () => console.log('running...'))
⑷. 存在的问题
- 前后端代码完全耦合在一起,不利于团队开发和维护
- 前端没有足够的发挥空间
- 由于内容都是在服务端动态生成的,所以服务端的压力较大
- SPA 应用可以无刷新展示页面,而这种传统模式用户体验一般
三、客户端渲染
1. 客户端渲染流程
随着 Ajax
技术的普及,使得客户端动态获取数据成为可能,因此服务端渲染的工作来到了客户端。
- 首先,客户端发起请求,请求网页地址
- 服务端返回一个空白的 HTML 页面
- 客户端拿到页面,执行里面的脚本代码(如果有动态数据会发起AJAX请求)
- 服务端收到请求之后进行查库操作,服务端把数据直接返回给客户端,客户端拿到数据,再来渲染页面(比如vue配合axios就是典型的客户端渲染)。
因此,服务端只需要负责数据的处理,客户端负责页面的展示;所以数据处理和页渲染就被分离开来,分别交付给前后端来完成,具有更好的可维护性,提高开发效率
2. 为什么客户端首屏渲染慢
- 因为 HTML 中没有实质性的内容,有的是 js 资源的引用,并且必须等到这些 js 加载并执行完成,才能呈现页面内容。
- 所以客户端渲染最起码要经历三次 http 请求周期:第一次是页面的请求,第二次是 js 对应的请求,第三次是动态数据请求
- 而传统的服务端渲染是页面直接输出,不用再去执行 js ,也不用再去发请求。
3. 为什么客户端不利于 SEO
SEO(Search Engine Optimization)又称搜索引擎优化,为近年来较为流行的网络营销方式,主要目的是增加特定关键字的曝光率以增加网站的能见度,进而增加销售的机会。
- 浏览器获取数据后,对于搜索引擎就要去分析:根据权重进行收录,如果发现新的链接就会进入另一个页面再去收录,才有可能通过打开搜索引擎搜索到你的页面。
- 相较于服务端渲染,客户端需要经过解析执行 js,才能渲染网页内容。而搜索引擎的程序不是浏览器,它拿到的是网页的html(无有利于 SEO的内容),不会像浏览器一样再去加载解析js
- 因为 HTML 中没有内容,所以对于目前的搜索引擎爬虫来说,页面中没有任何有用的信息,自然无法提取关键词,进行索引了。
四、现代化的服务端渲染(同构渲染)
1. 同构渲染流程
- 基于React、Vue等框架,客户端渲染和服务端渲染的结合
- 在客户端执行一次,用户实现服务器端渲染(首屏直出)
- 在客户端再执行一次,用于接管页面交互
- 核心解决SEO和首屏渲染慢的问题
- 拥有传统服务端渲染的优点,也有客户端渲染的优点。
- nuxt框架不仅仅是服务端渲染,而是【服务端】+【客户端】渲染
- 应用了nuxt框架之后,所有的Vue模板解析成js的工作都在服务端进行的,不仅会返回带有数据的渲染后的模板内容,还会返回不带数据的客户端SPA脚本,用来进行用户交互,但是数据与模板的结合并不一定在服务端进行操作
- 总的来说: 需要内容直出的页面就用服务端渲染,在服务端就将数据和模板进行整合到一起,然后一同返回给页面。而需要交互的页面使用的仍然是异步请求的方式,进行客户端渲染。
2. 如何实现同构渲染?
- 使用 Vue、React 等框架的官方解决方案
- 优点: 有助于理解原理
- 缺点: 需要搭建环境,比较麻烦
- 使用第三方解决方案
- React 生态中的
Next.js
- Vue 生态中的
Nuxt.js
- ······
- React 生态中的
3. Nuxt.js 示例
Nuxt.js 是一个基于 Vue.js 生态开发的一个第三方服务端渲染框架,通过它我们可以轻松构建现代化的服务端渲染应用。
具体实现代码: 可查看博主下一偏博客 - Nuxt.js 基础
4. 同构渲染应用的问题
开发条件有限:
- 浏览器特定的代码只能在某些生命周期钩子函数中使用
- 一些外部扩展库可能需要特殊处理才能在服务端渲染应用中运行
- 不能再服务端渲染期间操作DOM
- 某些代码操作需要区分运行环境
涉及构建设置和部署的更多要求:
- | 客户端渲染 | 同构渲染 |
---|---|---|
构建 | 仅构建客户端应用即可 | 需要构建两个端 |
部署 | 可以部署在任意web服务器中 | 只能部署在Node.js Server中 |
更多的服务器端负载:
- 在Node中渲染完整的应用程序,相比仅仅提供静态文件服务器,需要大量占用CPU资源
- 如果应用在高流量环境下使用,需要准备相应的服务器负载
- 需要更多的服务端渲染优化工作处理