共计 3960 个字符,预计需要花费 10 分钟才能阅读完成。
写在后面
SSR(Server-Side Rendering)并不是什么离奇的概念,前后端分层之前很长的一段时间里都是以服务端渲染为主(JSP、PHP),在服务端生成残缺的 HTML 页面
(摘自前端渲染模式的摸索)
也就是说,历经 SSR 到 CSR 的大改革之后,现在又从 CSR 登程去摸索 SSR 的可能性……仿佛兜兜转转又回到了终点,在这之间产生了什么?现在的 SSR 与当年的 JSP、PHP 又有什么区别?
一.SSR 大行其道
回到论坛、博客、聊天室仍旧炽热的年代,行业最佳实际是基于 JSP、PHP、ASP/ASP.NET 的动静网站
以 PHP 为例:
<?php if (count( $_POST) ): ?>
<?php include WTG_INCPATH . '/wechat_item_template.php' ?>
<div style="...">
<div id="wechat-post" class="wechat-post" style="...">
<div class="item" id="item-list">
<?php
$order = 1;
foreach ($_POST['posts'] as $wechat_item_id ) {echo generate_item_list( $wechat_item_id, $order);
$order++;
}
?>
</div>
<?php
$order = 1;
foreach ($_POST['posts'] as $wechat_item_id ) {echo generate_item_html( $wechat_item_id, $order);
$order++;
}
?>
<fieldset style="...">
<section style="...">
<p style="..."> 如果心中仍有疑难,请查看原文并留下评论噢。(<span style="font-size:0.8em; font-weight:600"> 特地要紧的问题,能够间接微信分割 ayqywx</span>)</p>
</section>
</fieldset>
</div>
<script>
function refineStyle () {var post = document.getElementById('wechat-post');
// ul ol li
var uls = post.getElementsByTagName('ul');
for (var i = uls.length - 1; i >= 0; i--) {uls[i].style.cssText = 'padding: 0; margin-left: 1.8em; margin-bottom: 1em; margin-top: -1em; list-style-type: disc;';
uls[i].removeAttribute('class');
};
}
document.addEventListener('DOMContentLoaded', function() {refineStyle();
});
</script>
</div>
<?php endif ?>
(摘自 ayqy/wechat_subscribers,一款用来主动生成微信公众平台图文音讯的 WordPress 插件)
这一时期网页内容齐全由服务端渲染,客户端(浏览器)接管到的是交融了服务数据的 HTML,以及大量内联的(表单)交互逻辑和款式规定,撑持着晚期大量动静网站的正是这种 纯 SSR 模式
但随着技术实际的深刻,这种模式逐步暴露出了一些问题:
- 性能差:每一个申请过去都要从新执行一遍数据逻辑和视图逻辑,动静生成 HTML,即使其中很大一部分内容是雷同的
- 机器老本高:Tomcat/Apache 等应用服务器的并发解决能力远不迭 nginx 之类的 Web 服务器,因而须要部署更多的机器
- 开发 / 保护难:前后端代码掺杂在一起,人员合作是个问题,并且批改保护要非常审慎(标签构造容易被毁坏)
面对这些问题,两个思路逐步变得清晰起来,动静拆散 与前后端分层,前者解决性能和机器老本的问题,后者解决开发 / 保护的问题
二. 动静拆散
为了充分利用 Web 服务器的动态资源解决劣势,同时加重应用服务器的累赘,将资源分为两类:
- 动态资源:图片、CSS、JS 等专用的,与具体用户无关的资源
- 动静资源:应用逻辑、数据操作等与具体用户密切相关的资源
两种资源离开部署,把动态资源部署至 Web 服务器或 CDN,应用服务器只部署动静资源。如此这般,动态资源响应更快了(浏览器缓存、CDN 减速),应用服务器压力更小了,大快人心
然而,视图逻辑却被咱们漏掉了,HTML 算作动态资源还是动静资源?
前后端分层就是为了答复这个问题
三. 前后端分层
视图逻辑的非凡之处在于:
- 与数据密切相关
- 服务端与客户端均可承载视图逻辑
也就是说,HTML 视图构造的创立和保护工作,能够由服务端实现,也能够在客户端实现,都依赖服务数据。但与服务端相比,客户端环境有一些劣势:
- 无需刷新(从新申请页面)即可更新视图
- 收费的计算资源
因而,视图逻辑划分到了客户端(即 CSR),以数据接口为界,分成前后端两层:
- 后端:提供数据及数据操作反对
- 前端:负责数据的出现和交互性能
自此,前后端各司其职,前端致力于用户体验的晋升,后端专一业务畛域,并行迭代,(不波及接口变动时)互不影响
四.CSR 如日中天
前后端分层之后,进入了 CSR 的黄金时代,摸索出了性能插件、UI 库、框架、组件等多种代码复用计划,最终造成了凋敝的组件生态
组件化的开发方式之下,纯 CSR 模式 日益流行:
<!DOCTYPE html>
<html>
<head>
<title>My Awesome Web App</title>
<meta charset="utf-8">
</head>
<body>
<div id="app"></div>
<script src="bundle.js"></script>
</body>
</html>
这种模式下,简直所有的页面内容都由客户端动静渲染而来,包含创立视图、申请数据、交融数据与模版、交互性能在内的所有工作,都交由一套数据驱动的组件渲染机制来全权治理,而不用再关注组件之下的 DOM 构造保护等工作,无效进步了前端的生产效率。但一些问题也随之而来:
- 在组件树首次渲染完之前,页面上无奈展现任何内容,包含 loading
- 数据申请必须等到所属组件开始渲染能力收回去
这些问题的本源在于目前的 组件渲染流程是同步阻塞的,对首屏性能提出了挑战:
- 低端设施上 JS 执行效率低,白屏工夫长
- 弱网环境下数据返回慢,loading 工夫长
CSR 尽管利用了用户设施的计算资源,但同时也受其性能、网络环境等不可控因素的制约。于是,大家又从新将眼光汇集到了 SSR
五.SSR 卷土重来
SSR 模式下,首屏内容在服务端生成,客户端收到响应 HTML 后可能间接出现内容,而无需等到组件树渲染结束
尽管核心思想都是在服务端实现页面渲染工作,但现在的 SSR 与先前大不相同,体现在:
- 出发点:为了更快、更稳固地呈现出首屏内容
- 成熟度:建设在前端成熟的组件体系、模块生态之上,基于 Node.js 的同构计划成为最佳实际
- 独立性:依然放弃着前后端分层,不与业务畛域的应用服务强耦合
也就是说,现在的 SSR 是为了解决前端层的问题,联合 CSR 优化内容加载体验,是在 CSR 多年积淀之上的扩大,与现有的前端技术生态放弃着良好的相容性。而当年的 SSR 更多地是为了实现性能,解决饥寒问题
再看当年 SSR 面临的几个问题:
- 性能差:每一个申请过去都要从新执行一遍数据逻辑和视图逻辑,动静生成 HTML,即使其中很大一部分内容是雷同的
- 机器老本高:Tomcat/Apache 等应用服务器的并发解决能力远不迭 nginx 之类的 Web 服务器,因而须要部署更多的机器
- 开发 / 保护难:前后端代码掺杂在一起,人员合作是个问题,并且批改保护要非常审慎(标签构造容易被毁坏)
引入 SSR 之后这些问题卷土重来,但这些年的技术倒退为解决这些问题提供了新的思路:
- 实时渲染的性能问题:动静拆散的思路依然实用,例如 Static Generation
- 服务器资源老本问题:云计算的倒退无望大幅升高机器老本,例如 Node FaaS
- SSR 局部与 CSR 局部的开发 / 保护问题:同构为解决开发 / 保护难题提供了一种新思路(之前的思路是前后端分层,但这一次分不开了),保护同一份代码,跑在不同的运行环境输入不同模式的指标产物
其中,Static Generation(也叫 SSG,Static Site Generation)是指在编译时生成动态 HTML(可部署至 CDN),防止实时渲染的性能开销:
Static Generation (Recommended): The HTML is generated at build time and will be reused on each request.
但并非所有页面都能在编译时动态生成,一种可行的实际计划是将 SSR 与 Static Generation 联合起来,只对内容依赖个性化数据、或者频繁更新的页面走 SSR,其余场景都走 Static Generation:
You should ask yourself: “Can I pre-render this page ahead of a user’s request?” If the answer is yes, then you should choose Static Generation.
至此,沉寂多年的 SSR 又焕发出了新的生机
参考资料
- What is the point of SSR these days?
- Two forms of Pre-rendering
有所得、有所惑,真好
关注「前端向后」微信公众号,你将播种一系列「用 心原创」的高质量技术文章,主题包含但不限于前端、Node.js 以及服务端技术
本文首发于 ayqy.net,原文链接:http://www.ayqy.net/blog/dife…