前言
当下用的比较多的是单页面应用,它具有以下优点:
- 具有较好的用户体验
- 渲染性能好
- 可维护性高
相应着缺点也很明显:
- 首页加载速度时间过长
- 不利于 SEO
服务端渲染就算为了解决这两个缺点。这边的服务端渲染并不是以前的 JSP、PHP 之类的做法,而是现代化的服务端渲染,也可以叫同构渲染。为了更好的理解同构渲染,下面讲解下各个渲染方式:
- 传统的服务端渲染
- 客户端渲染
- 现代化服务端渲染(同构渲染)
什么是渲染
这边指的渲染不是如何渲染,而是在哪里渲染,或者说是在哪里拼接成一个完整的 html 内容。
如果是客户端渲染,服务端返回的是类似这样的代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<div id="app"></div>
</body>
</html>
这样的代码只有 head 信息,body 的内容几乎为空,所以这样的页面可称为空页面。真正的网页内容是由客户端通过 JavaScript 生成的,这便是客户端渲染。
而服务端渲染,是在服务端生成完代码,返回给客户端的时候就是一个完整的 html 内容。
这便是这边指的渲染。
而渲染通常会借助模板引擎,模板引擎会将内容模板和数据分开,同一个模板,可因数据的不同而渲染出不同的内容,所以渲染又可以看作为数据 + 模板。
传统的服务端渲染
这种渲染方式是最早期的做法,所有页面都在服务端渲染,采用的类似 JSP、PHP 之类的模板引擎在进行渲染。工作流程如下图:
这边以 NodeJS 为例,实现一个传统的服务端渲染 Demo,代码在 在这
这种渲染方式存在这样几个问题:
- 应用的前后端部分完全耦合在一起,在前后端协同开发方面会有非常大的阻力;
- 前端没有足够的发挥空间,无法充分利用现在前端生态下的一些更优秀的方案;
- 由于内容都是在服务端动态生成的,所以服务端的压力较大;
- 相比目前流行的 SPA 应用来说,用户体验一般;
客户端渲染
这种方式是当前比较流行的方式,Vue、React、Angular 默认都是采用这种方式开发。由服务端返回一个空页面和 JS 引用代码,在客户端完成渲染。工作流程如下图:
优点就是解决了传统的服务端渲染存在的缺点,同时也伴随着一些缺点:
- 首屏渲染慢:因为 HTML 中没有内容,必须等到 JavaScript 加载并执行完成才能呈现页面内容。
- SEO 问题:同样因为 HTML 中没有内容,所以对于目前的搜索引擎爬虫来说,页面中没有任何有用的信息,自然无法提取关键词,进行索引了。
现代化服务端渲染
这是一个传统服务端渲染和客户端结合起来的方案,由服务端负责首次页面渲染,让客户端接管后续交互渲染,两端共同构建应用,所以称之为同构渲染。工作流程如下图:
这种方案解决了客户端渲染存在的缺点,又保留了客户端渲染的优点,是目前最佳的解决方案。这种方案已经有成熟的库可以实现,比如 NuxtJS,具体如何实现,请移至 NuxtJS 文档
这种方案也存在者一些缺点:
开发条件所限。
- 浏览器特定的代码只能在某些生命周期钩子函数中使用
- 一些外部扩展库可能需要特殊处理,才能在服务器渲染应用程序中运行
- 不能在服务端渲染期间操作 DOM
- 某些代码操作需要区分运行环境
涉及构建设置和部署的更多要求。
客户端渲染 同构渲染 构建 仅构建客户端应用即可 需要构建两个端 部署 可以部署在任意 Web 服务器中 只能部署在 Node.js Server 更多的服务器端负载。
- 在 Node.js 中渲染完整的应用程序,显然会比仅仅提供静态文件的 server 更加大量占用 CPU 资源
- 如果你预料在高流量环境下使用,需要准备相应的服务器负载
- 需要更多的服务端渲染优化工作处理
如何选择?
以上介绍了三种渲染方式,第一种可以说已经被淘汰了,不需要考虑。第三种虽说是目前最佳的解决方案,但也有其对应的缺点,事实上更多的情况是采用第二种方案。
对于 SSR(现代化服务端渲染)和 CSR(客户端渲染)的选择,在于项目的需求。正常情况应该优先考虑 CSR,如果存在以下情况才去考虑 SSR:
- 项目有 SEO 的需求
- 追求极致的用户体验
满足一点就可以考虑使用 SSR,否则建议使用 CSR 。