959 字
5 分钟

构建产物 16 MB,访客每次只下 28 KB

统计 dist 目录发现 16 MB、313 个文件,其中 1.6 MB 的 Mermaid 图表引擎从来没被下载过。这篇把「部署体积」与「访客成本」分清:什么进了关键路径、什么按需加载、什么可以被缓存一年。
10月24日 23:20

跑完性能体检后我一直有两套数字,但从来没把它们放在一起看:

  • 部署体积:dist 目录 16.04 MB、313 个文件;
  • 访客成本:首页实际传输 27.9 KB(brotli 压缩后)。

差 570 倍。这篇就把这个差距拆开——哪些体积是真的,哪些是错觉。

dist 里到底装了什么#

dist 构成:HTML 37%、WebP 31%、JS 21%

类型文件数体积占比
HTML575.95 MB37.1%
WebP 配图914.91 MB30.6%
JS883.31 MB20.6%
字体591.02 MB6.4%
XML(sitemap / rss)40.37 MB2.3%
JSON / CSS / SVG80.47 MB4.7%

最扎眼的是 JS 那 88 个文件、3.31 MB。而最大的六个文件里有四个是图表引擎:

585.3 KB  _astro/mermaid.core.js
481.0 KB  _astro/wardley.js
431.4 KB  _astro/cytoscape.esm.js
253.4 KB  _astro/katex.js

Mermaid 全家桶 1.6 MB。 而这个站目前一张 Mermaid 图表都没有。

但访客从没下载过这 1.6 MB#

因为它是动态 import 的:

let mermaidLoader: Promise<any> | null = null;
const loadMermaid = async () => {
  if (!mermaidLoader) {
    mermaidLoader = import("mermaid").then((mod) => mod.default);
  }
  return mermaidLoader;
};

只有当页面里真的出现 ```mermaid 代码块时才会调用它。于是这 1.6 MB 变成了永远不会被请求的部署体积——它在 dist/ 里占位,但不进任何人的关键路径。

部署体积 16 MB,单次访问 28 KB

实测传输量:

页面传输(brotli)
首页 /27.9 KB
文章页 /posts/blog-view-counter/47.5 KB

三个让差距变大的机制#

1. 压缩:130 KB → 28 KB。 HTML 平均每页 104 KB(未压缩),Cloudflare 默认开 brotli,压到 25~30 KB。这是最容易忽略的一半——看 dist 的体积永远会高估 4~5 倍。

2. 按需加载:1.6 MB 永不下载。 除了 Mermaid,KaTeX(数学公式)也是同一个模式。这类”可能用得上”的依赖放动态 import,代价从「每个访客」变成「零」。

3. 长缓存:第二次访问不再请求。 构建产物文件名带内容哈希,/_astro/ 下全部是:

cache-control: public, max-age=31536000, immutable

(这条是三层缓存那篇改的,之前所有资源都是 max-age=0。)

三个机制叠起来,才有了「16 MB 部署、28 KB 首访、几乎零次访」。

顺手修掉的一个小浪费#

拆 HTML 时发现每页 40 KB 是内联脚本(44 个 <script>),其中最大的那块里塞着我写的解释性注释——is:inline 的脚本会被原样输出,注释也算字节。

改法是把长注释搬到文档、脚本里只留一行结论:

改前改后
首页 HTML134 KB132.9 KB
内联脚本合计40.0 KB39.5 KB

省下 509 字节/页。数字很小,但它说明一件事:is:inline 的脚本要当成”发给用户的源码”来写,注释不是免费的。

(真正的大头在别处:40 KB 内联脚本里,最大的一块 6 KB 是 Cookie 横幅的引导代码——这也是它成为 LCP 元素的原因之一,见和横幅抢 LCP。)

该看哪个数字#

我的结论是:看三个,而不是一个。

数字看什么什么时候看
部署体积部署限制(Cloudflare 单 Worker 2 万文件 / 单文件 25 MiB)加依赖时
首访传输真实的首屏成本优化性能时
二次访问缓存是否生效改缓存策略时

只看第一个会去删没用的依赖(比如把 Mermaid 删了),但收益是 0——因为它本来就没被下载。只看第二个会忽略部署限制。三者一起看,才知道该动哪里。

每个页面的静态产物都是同一套模板,压缩后 25~30 KB

小结#

  • 部署体积 ≠ 访客成本,中间有压缩、按需加载、缓存三道闸;
  • 动态 import 的依赖要算「永远不下载」,不要为了 dist 好看去删它;
  • 内联脚本属于源码分发,注释也算字节;
  • 判断优化优先级时,先量一次「首页压缩后到底多少 KB」——那才是用户付出的代价。

这篇文章是否对你有帮助?

发现错误或想要改进这篇文章?

在 GitHub 上编辑此页

文章修订历史 (1 次)

查看变更记录
10月24日 23:18:07 c20be15

docs(baseline): 第 30 轮终检——数字更新到最终状态,补第 28~30 轮小结

构建产物 16 MB,访客每次只下 28 KB
作者
peroe
发布于
10月24日 23:20
许可协议
CC BY-NC-SA 4.0

相关文章