静态部署(static hosting) / 静态站点生成(SSG, Static Site Generation): 页面在发布之前就生成成一批现成的文件(HTML、样式、脚本、图片), 放到一台只负责「把文件递出去」的机器或对象存储上;访客来了就拿到文件,服务器不做任何计算。 把内容与模板拼成这批文件的那一步,叫静态站点生成。 就像提前把每个页面都印成传单:谁来都给同一张,发传单的机器只管递纸,不用现场排版;传单要改,就得重印一批再送到各处。
服务端渲染(SSR, Server-Side Rendering): 每个请求到来时,服务器上跑一段程序,把数据填进模板、拼出完整的 HTML 再发出去。 你一问,后台当场给你拼一张:同一个网址,不同的人、不同的时刻能拿到不一样的内容,代价是每次都有人现做。
客户端渲染(CSR, Client-Side Rendering): 服务器只发一个几乎空的 HTML 外壳和脚本;浏览器先下载并执行脚本,再去接口取数据,在页面里把内容拼出来。 先给你一个空盒子加一本说明书:盒子里的东西不由发货方装,而是你打开后照着说明书自己去取、自己装。
容器部署(container deployment): 把程序和它依赖的运行环境一起打包成容器(container)(自带依赖、换哪台机器都照跑的运行单元), 冻结成只读的镜像(image)(能整块搬走、拿它就能起容器的打包快照,见 镜像、容器、仓库), 再交给某台机器或编排器(orchestrator)(排布容器跑在哪台机器、起几份、挂了谁来补的那层软件, 如多机才用得上的 Kubernetes)跑起来; 镜像搬到哪台机器上都一样。 把程序和它的房间一起打包:搬到哪台机器上,打开门就能住,不用在那边重新装修、重新配家具。
四种做法面对的是同一件事:这段页面内容什么时候算出来、在哪台机器上算。 这件事定下来,机器要多大、账单怎么长、内容多久能更新,才都跟着定下来。
前三种在同一条轴上互相替代:算发生在发布前还是请求时;若是请求时,又由服务器还是浏览器来做。 容器部署在另一条轴上:它管程序住在哪,所以能和上面任何一种叠加。
五个问句就是五条判据;横着读一行,做法基本就定了。
| 做法 | 发布前内容已存在? | 每个请求还要算? | 算在哪台机器 | 有能单独拿走的产物? | 改内容要重新发布? |
|---|---|---|---|---|---|
| 静态部署 | 是 | 不用 | 不用算,只有发文件的机器 | 有:一堆 HTML 文件 | 要:重新构建再上传 |
| 服务端渲染 | 否,只有模板和代码 | 要,每个请求都算 | 你的服务器或托管的运行环境 | 没有「最终页面」这个产物 | 改数据不用,改代码要部署 |
| 客户端渲染 | 否,只有外壳和脚本 | 页面不在服务器算 | 计算在访客的浏览器里 | 有:脚本与前端构建产物 | 改数据不用,改前端要发布 |
| 容器部署 | 看里面装的是什么 | 看里面跑的是什么 | 你管的机器或编排集群 | 有:容器镜像 | 要:重建镜像并滚动更新 |
最后一行为什么写「看」:容器是把程序装起来的那层壳,壳里可能是静态文件服务器,也可能是服务端渲染程序。 判据本身没变 —— 先看壳里装的是什么,再回到前几行。
矩阵没列的那一种:传统服务器部署。在一台常开的机器上装好运行时、把代码放上去,每个请求都由这台机器现算现给 —— 它就是没有容器这一层的服务端渲染,所以不单列一行,归在「服务端渲染」那一行;矩阵仍按四种做法列。
① 静态部署:文件直接交给访客。跑一次 SSG(静态站点生成)把内容刷成一堆文件, 再交给 静态托管(static hosting)或对象存储(object storage,把文件整块存起来、按网址取回的服务,如 S3);把这批文件送到离访客最近的一站, 由 CDN(content delivery network,内容分发网络 —— 提前把文件铺到各地节点、让访客就近取的服务, 见 MDN CDN)代劳。 这条构建命令通常由 CI/CD 在每次推送后自动跑,产物直接上传。
npx vitepress build docs # 或 hugo --minify、astro build
# 产物在 dist/ 或 public/,推到 Cloudflare Pages / Netlify / Vercel
② 服务端渲染:每次请求服务器拼好整页 HTML 再发。这就是 SSR: 请求进来先取数据、跑模板、拼出完整页面,连同首屏内容一起返回, 程序跑在 Node.js 这类运行时里。
next build && next start # 或 nuxt build,跑在 Node 运行环境里
③ 客户端渲染:先发一个空壳 HTML 加脚本,浏览器再取数拼页面。这就是 CSR: HTML 里几乎只有挂载点和脚本;脚本跑起来后向接口要数据,再写进页面。
npm run build # 得到外壳与前端脚本
# 数据由浏览器请求 /api/orders 这类接口后自己渲染
④ 容器部署:程序连环境一起打包,换台机器也一样跑。镜像(image)里带上运行时与依赖,
单机 docker run 就能起,多机才交给编排器调度。
docker build -t my-app:1.0 . # 打成镜像,推送到镜像仓库
docker run -p 8080:8080 my-app:1.0
# 多机场景:镜像交给 Kubernetes,由它挑机器、重启、扩副本
两种常见混搭:静态外壳 + 少量接口(评论、搜索、表单提交);或者服务端渲染拼出首屏, 再由浏览器里的脚本接管后续交互(这一步叫 hydration,水合)。真实产品很少只用其中一种。
dist/,推到 Cloudflare Pages 或 Netlify,由 CDN 直接发文件,
请求上几乎不付计算钱,团队小也不用自己管服务器。一句话收口:先答「什么时候算」,再答「住在哪」 —— 前者决定内容怎么生成,后者决定环境怎么搬。
docker run、docker compose 都算容器部署;Kubernetes 是编排器,给多机多副本的场景用,
规模小的时候它带来的运维复杂度远大于收益。三个场景,每题只在四种做法里选一个;选完立刻看到这笔账记在哪儿。
1. 一个只放产品文档的站,内容跟着代码仓库一起更新;团队小,不想自己维护服务器。
对。内容不按人变、不按秒变,一次构建就把页面定死,让 CDN 替你挨请求,请求上几乎不用付计算钱。代价在第 5 节:改一句文案也要重新构建、重新上传,再让旧缓存失效;要按人显示的部分只能另开接口。
2. 一个商品详情页:库存和价格随时在变,但它必须能被搜索引擎收录,分享出去的链接还要有预览。
对。内容和时刻绑在一起,发布前算不出来,只能挪到请求时算;交给服务器拼,首屏 HTML 里就带着库存、价格和分享预览。代价是每个请求都占一次计算:流量一涨,机器数量和账单跟着涨,TTFB 也被服务器的拼接速度拴住。
3. 一个每天定点跑数据同步的小服务,依赖一个只有 Linux 才有的系统库,还要求换台机器跑起来一模一样。
对。定时任务和特殊系统库问的不是「页面什么时候算」,而是「程序住在哪」;把程序和依赖一起打成镜像,换台机器跑起来才一样。代价是运维复杂度:要管镜像构建、镜像仓库、发布与回滚,排查一次故障要穿过好几层。