4.6 万张地图页怎么秒开?静态生成 + 边缘加速实战
上一篇聊完渲染,这篇聊一个工程上的硬骨头:页面太多怎么办。我在 GeoJSONcn 项目里,光行政区划边界页就有省 34、市 364、区县 2800+、乡镇 4 万多,加起来 4.6 万张静态页。怎么让它们在国内 4G 网络下还能秒开?这套思路我觉得挺值得唠唠,因为它几乎不挑技术栈,谁都能抄。
核心思路:能预生成的,绝不在请求时算
很多人的第一反应是"用框架 SSR(服务端渲染)"。但 4.6 万页每次请求都现算?服务器直接躺。正确姿势是:页面在构建阶段就烤成静态 HTML,用户请求时只管把文件发出去。
这叫构建期预渲染(build-time prerendering)。4.6 万页本质就是 4.6 万个 .html 文件,提前生成好躺在那儿。
链路:用户 → 边缘 → 源站
光生成静态文件还不够,文件得离用户近。我的链路是:
浏览器
→ 阿里云 ESA(国内边缘节点,30 天缓存)
→ Cloudflare Worker(路由 + 轻加工)
→ Cloudflare R2(存静态文件)
关键点:ESA 把热点页冻在离用户最近的国内节点。用户访问省页,请求根本到不了源站,边缘直接吐缓存,毫秒级。这比任何优化代码都管用。
性能账:边缘缓存为啥这么猛
算笔账你就懂了:
- 没缓存:每次请求 R2 读文件加 Worker 处理,跨境链路几十到几百 ms;
- 有边缘缓存:热点页命中边缘,国内节点直出,首字节常常小于 50ms。
4.6 万页里,省市页是高频,乡镇页是长尾。高频页命中边缘缓存后几乎零成本;长尾页偶尔回源一次,ESA 顺手缓存上,下次也快。
几个踩过的坑
1. 缓存 TTL 要够长。行政区划边界几个月才变一次,ESA 设 30 天完全合理。别用默认短 TTL,不然边缘命中率上不去。 2. 源站别做字符串拼接。Worker 只做读文件加设响应头,不要每请求改 HTML 内容,CPU 白烧。需要动态的部分(比如相关阅读),用 KV 加轻量加工兜底(下篇讲)。 3. 压缩交给边缘。HTML/CSS/JS 的 gzip/br 让 CDN 协商,源站只存原文,别自己先压一层把事搞复杂。 4. 预热长尾。4.6 万页不可能都自然变热。上线后我写了个脚本,按计划批量预热地图数据页,把冷页主动推到边缘,避免第一批用户替你踩回源慢的坑。
这套思路能用在哪
你不一定是做地图的。只要是内容相对固定、页面数量巨大的场景,商品详情页、文档站、博客,这套"构建期预渲染加边缘缓存"都适用。核心就一句话:把算力从请求期挪到构建期,把文件挪到离用户最近的地方。
我在 GeoJSONcn 就是这么干的,4.6 万张边界页国内访问很稳。想看实际效果,随便点个省市区就能感受到。
最后
海量页面别 SSR 现算,构建期烤成静态 HTML;边缘缓存(ESA/Cloudflare 之类)是性能上最狠的一招;TTL 设长、源站零加工、压缩交边缘、长尾要预热。
下一篇聊个进阶玩法:页面是静态的,但"相关阅读"这种要动态关联的内容,怎么用 Serverless(KV + Worker)低成本实现?