分离之后,服务器只发数据、浏览器自己拼页面——服务器省下的是时间,代价转移到用户的设备上。
2-9 讲了服务器怎么把页面做出来。这一条讲一个更彻底的改动:干脆不让服务器做这件事。它是本章里最关键的一次分工重排,也是理解今天前端、后端、接口这些词的前提。
一、从整页发出到只发数据
早期做法是:服务器把整页 HTML 拼好,浏览器拿到的就是一个成品。浏览器的工作很轻,几乎是照着画。
分离之后反过来了:服务器只发数据,浏览器拿到数据自己拼。
这个改动听起来只是搬了个位置,但两边的工作量变了。
二、动手 Demo:服务器省了什么,用户等什么
before, after = 12, 2
print("服务器渲染一页 %d 毫秒,只出数据 %d 毫秒" % (before, after))
print("省下 %.0f%%" % ((1 - after * 1.0 / before) * 100))
print("10 万次访问:%d 秒 -> %d 秒" % (before * 100000 / 1000,
after * 100000 / 1000))
实跑输出:
--------------------------------------------------------------------
D10 将客户端与服务器分离:脚本语言
--------------------------------------------------------------------
早期的动态页面,是服务器把整页 HTML 拼好再发出来。
分离之后,服务器只发数据,页面由浏览器自己拼。
----------------------------------------------------------------------------------------
分离前 分离后
----------------------------------------------------------------------------------------
服务器返回什么 120 KB 完整 HTML 2 KB JSON
谁在拼页面 服务器 浏览器
服务器耗时 约 12 毫秒 约 2 毫秒
10 万次访问合计 1200 秒 200 秒
----------------------------------------------------------------------------------------
服务器省下 83% 的时间,代价转移到了浏览器身上:
页面得等 JavaScript 下载完、跑起来,内容才出现。
这就是为什么后来又要用服务端渲染、静态生成把首屏补回来。
分离这件事今天普遍到什么程度:
----------------------------------------------------------------------------------------
口径 比例
----------------------------------------------------------------------------------------
用现代前端框架 + 独立构建的团队 72%
其中做到完全前后端分离的 48%
中大型团队(后端 20 人以上)里完全分离的 近 70%
----------------------------------------------------------------------------------------
分开之后,两边的活儿也分家了,各自用各自的脚本语言:
----------------------------------------------------------------------------------------
位置 主力语言 管什么
----------------------------------------------------------------------------------------
浏览器端 JavaScript / TypeScript 交互、动画、页面局部更新
服务器端 PHP 内容型网站、CMS(2-12 展开)
服务器端 Python / Java / Go / C# 业务系统、接口、高并发
----------------------------------------------------------------------------------------
有一句话要记住:【脚本语言】这个词,在两边指的是完全不同的东西。
前端脚本跑在用户的电脑上,用户能在开发者工具里看到它、改它——
所以【前端代码不是秘密】,任何需要保密的东西都不能只放在前端。
后端脚本跑在你看不见的服务器上,那边才是真正守门的地方。
读这个输出:服务器的负担降到五分之一左右。这么大的差距,正是这套做法被普遍采用的原因。但账不能只看一半——省下的这部分并没有消失,它变成了用户那边的等待:页面得等脚本下载完、跑起来,内容才出现。
三、代价与补法
代价是首屏变慢,而且对爬虫不友好(爬虫拿到的是一个空壳)。所以后来又要用服务端渲染、静态生成把首屏补回来——这就是 2-5 里说的那几种渲染策略的由来。
换句话说:静态、动态、服务端渲染、客户端渲染,它们不是互相取代的关系,而是在同一件事上反复调整分工。每一次调整,都是在【服务器省不省】和【用户等不等】之间重新划线。
四、两边的语言也就此分家
分工一定,语言自然分开:浏览器端只有 JavaScript(及其带类型的版本),服务器端则是一堆选择(PHP、Python、Java、Go、C#)。
这里有一条安全上的硬规矩,值得反复强调:前端脚本跑在用户的电脑上,用户能看到它、也能改它。所以前端代码不是秘密——任何需要保密的东西,都不能只放在前端。
很多人第一次做登录功能时会犯这个错:把密码校验写在页面里。那等于把钥匙摆在门垫下面。
五、⚠️ 2026 现状
分离这件事今天已经普遍到七成上下:用现代前端框架 + 独立构建流程的团队约 72%,其中做到完全前后端分离的约 48%,中大型团队里接近 70%。
但方向也在往回摆一点:过度分离带来的首屏代价,正被服务端渲染、静态生成、边缘渲染一层层补回来。这不是走回头路,是在【谁来做这件事】上继续微调。
30 秒实验
- 按 F12,切到 Network 面板,刷新一个你常用的网站。
- 在筛选框里选 Fetch/XHR,看看除了页面本身,还额外请求了多少份数据。
- 再选 JS,看看脚本加起来有多大——这几十万字节,就是【浏览器自己拼页面】的成本。
常见误区
- 错误:前后端分离只是分工问题,和技术无关。——纠正:它改变了服务器做什么、浏览器做什么,是整个架构的重新分工。分工变了,性能特征、错误发生的位置、调试的方式全都会跟着变。所以它不是组织问题,是技术问题。
- 错误:前端代码是安全的,用户看不到。——纠正:用户不仅能看到,还能改。脚本就在他的浏览器里跑,他能改完再提交。所以一切校验都要在服务器端再做一遍——前端校验只是为了让用户少等一会儿,不是防线。
- 错误:分离以后服务器就没事干了。——纠正:服务器省的是拼页面的时间,不是它该负的责任。数据从哪来、谁有权限拿、能不能改,全在服务器那边。把活推给前端,不等于把守门的职责也推过去。
- 错误:既然分离让首屏变慢,那就说明它不好。——纠正:这是一个取舍,不是缺陷。分离换来了多端复用(同一套接口供网页、App、小程序用)和前端独立发布的能力。首屏的代价后来用服务端渲染补上了——这就是技术演进的正常样子:先解决主要矛盾,再回头补副作用。
自测三问(点开对答案)
1. 分离之后,服务器的负担为什么能降那么多? —— 因为它**只负责拿出数据,不再负责把它拼成一整个页面**。拼页面这件事(模板渲染、组装 HTML)被搬到了浏览器上。**省下的正是这部分【重复且可以并行】的工作**——同一个页面有一万个用户看,就省了一万次。 2. 为什么【前端代码不是秘密】这句话值得反复强调? —— 因为**它是最容易犯、后果最重的一类错误**。前端脚本在用户机器上跑,他很轻松就能看到、甚至改掉。**任何只在前端做的校验,等于没有校验**——真正的门必须锁在服务器那边。 3. 分离带来的首屏代价,后来是怎么补的? —— **把一部分拼页面的活又搬回服务器**(服务端渲染),或者干脆提前算好(静态生成)。**注意这不是否定分离**:接口复用、独立部署这些好处都留着,只是把首屏这一段单独拿出来优化。**这是典型的【主要问题解决了,再补副作用】。**- ☐ 下一节(2-11 客户端的脚本语言:JavaScript、TypeScript)
相关笔记
- 程序的启动 —— 上一节:服务器怎么把页面做出来
- 独立于浏览器之外的Web连接机制 —— 页面与接口拿回的数据量差多少
- 浏览器的功能 —— 浏览器把文件画成画面的十一步
- CSV、XML、JSON、YAML —— 分离之后两边交换的格式
- 🕸️ Web技术原理 · 索引