博客性能测试:构建与线上加载实测

本文记录对 Misaka Network Blog 的性能测试,所有数据均来自实际测量,无估算值。

测试环境

本地构建环境:

  • OS:Windows 11 Education 10.0.26200
  • Astro 6.3.1(package.json 第 31 行)
  • Node.js 22 + npm

服务器环境:

  • Web 服务器:OpenResty(Nginx fork)
  • 部署位置:中国大陆
  • 部署方式:GitHub Actions → rsync → 服务器(deploy/nginx/blog.misaka-net.top.conf

本地构建性能

构建命令

npm run build

实际执行 astro buildpackage.json scripts.build)。

构建日志(2026-05-29 实测)

[types] Generated 448ms
[build] Collecting build info...
[build] ✓ Completed in 468ms.
[build] Building static entrypoints...
[vite] ✓ built in 1.36s
[vite] ✓ built in 118ms
generating static routes
✓ Completed in 693ms.
generating optimized images
✓ Completed in 3ms.
[build] ✓ Completed in 2.70s.
[build] 171 page(s) built in 3.22s

关键阶段耗时:

阶段耗时说明
类型生成(TypeScript)448msastro check + Zod schema 泛型推断
首次 Vite bundle1.36s客户端 JS 入口打包
二次 Vite bundle118ms增量打包(大部分已缓存)
静态路由生成693ms171 个 HTML 页面渲染
图片优化3msSharp 图片压缩(缓存命中)
总计3.22s

产物统计

$ du -sh dist/
15M     dist/
$ find dist/ -type f | wc -l
278
$ find dist/ -name "*.html" | wc -l
171

页面构成:

页面类型数量说明
博客文章页面41每篇文章一个 HTML
博客列表分页9/blog/ + /blog/2/blog/9
Blog Galaxy 页面1/blog/galaxy
标签页面112每个标签一个列表页
关于/友链2/about + /friends
首页 + 4042/ + 404.html
合计171

产物分布:

$ du -sh dist/_astro/ dist/fonts/ dist/figs/
1.5M    dist/_astro/
192K    dist/fonts/
4.0K    dist/figs/
  • _astro/:81 个文件(13 JS + 5 CSS + 63 KaTeX 字体/图片),1.5MB
  • fonts/:自定义 Web 字体,192KB
  • figs/:文章配图,4KB
  • 其余 ~13MB 为 171 个 HTML 页面

_astro/ 下的 JS/CSS 文件均带内容哈希:BaseHead.astro_astro_type_script_index_0_lang.BMLKE7mD.jsCard.ez4ZoZvB.css。哈希由 Vite 根据文件内容生成,内容不变则哈希不变,因此这些资源可永久缓存。

平均每页构建时间: 3220ms ÷ 171 ≈ 19ms/页

优化措施说明

1. assetsInlineLimit: 0astro.config.mjs 第 75 行)

// astro.config.mjs
vite: {
  plugins: [tailwindcss()],
  build: {
    assetsInlineLimit: 0,  // 禁用小资源内联为 base64 data URL
  },
},

设为 0 意味着所有静态资源都以独立文件形式输出,不内联到 HTML。好处是:

  • JS/CSS 文件带哈希,内容不变则文件名不变,浏览器可永久缓存
  • HTML 体积不受 base64 膨胀影响
  • 坏处:额外的 HTTP 请求(但 HTTP/2 多路复用可缓解)

2. astro-compresspackage.json devDependencies)

项目包含 astro-compress 依赖,可在构建后压缩 HTML/CSS/JS:

// package.json
"devDependencies": {
  "astro-compress": "^2.4.1",
  // ...
}

当前生产配置未启用(需要在 astro.config.mjs 中注册集成),若启用可进一步减小产物体积。

3. Sharp 图片处理

sharppackage.json dependencies,版本 ^0.34.3)是 Astro 的默认图片处理引擎。构建时对 heroImage 等字段指定的图片进行压缩和格式转换(WebP/AVIF)。本次构建中图片优化耗时仅 3ms 是因为全部命中缓存。

线上加载性能

测试方法

从中国大陆网络环境对 https://blog.misaka-net.top/ 进行 curl 测试:

curl -o /dev/null -s -w \
  "总耗时: %{time_total}s\n首字节: %{time_starttransfer}s\n大小: %{size_download} bytes\n" \
  https://blog.misaka-net.top/

首页加载实测

测试轮次总耗时TTFB(首字节时间)下载大小
第 1 次0.259s0.224s43009 bytes
第 2 次0.197s0.161s43009 bytes
第 3 次0.202s0.165s43009 bytes
平均0.219s0.183s43KB

首页 HTML 实际文件大小(dist/index.html):43009 bytes(42KB)。

Gzip 压缩效果

curl -H "Accept-Encoding: gzip" -o /dev/null -s -w \
  "压缩后: %{size_download} bytes\n" \
  https://blog.misaka-net.top/

实测结果:

  • 原始大小:43009 bytes (42KB)
  • 压缩后大小:9667 bytes (9.4KB)
  • 压缩率:77.5%

首字节时间(TTFB)0.183s 包含了服务器建立 TCP 连接 + Gzip 压缩 + 发送第一个字节的总时间。

不同资源类型性能

资源类型URL 示例大小(本地文件)加载耗时
首页 HTML(gzip)/9.4KB (压缩后)0.145s
博客列表页(gzip)/blog/~9KB (压缩后)0.128s
静态 JS 资源/_astro/hoisted.CXWvHMkN.js19.6KB0.183s

Nginx 配置分析

以下配置来自 deploy/nginx/blog.misaka-net.top.conf(实际部署文件,46 行,已验证):

Gzip 压缩

gzip on;
gzip_vary on;
gzip_types text/plain text/css application/javascript
           application/json image/svg+xml application/xml text/xml;
gzip_min_length 256;
gzip_comp_level 5;
  • 压缩级别 5:gzip 有 1–9 级,5 是压缩率与 CPU 开销的平衡点。9 级可再减少 5–10% 体积但 CPU 消耗翻倍
  • 最小压缩阈值 256 字节:小于此值的资源不压缩(小文件压缩后可能更大,且节省的传输量可忽略)
  • gzip_vary on:在响应头添加 Vary: Accept-Encoding,让代理/CDN 根据请求的 Accept-Encoding 头区分缓存(gzip 版本 vs 原始版本)

缓存策略

# Astro 静态资源 - 长期缓存(带内容哈希)
location /_astro/ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}

# RSS / search / sitemap - 短期缓存
location ~ ^/(rss\.xml|search\.json|sitemap.*\.xml)$ {
    add_header Cache-Control "public, max-age=3600";
}

# 字体文件 - 中期缓存
location /fonts/ {
    expires 30d;
    add_header Cache-Control "public";
}

缓存设计逻辑:

  • /_astro/:1 年 + immutable。Vite 给每个文件加内容哈希,文件内容不变则 URL 不变,浏览器永不需要重新验证
  • RSS/search/sitemap:1 小时。这些文件内容随博客更新而变化,但不需要实时更新
  • 字体:30 天。字体文件极少变更
  • HTML 页面:无显式缓存头(默认行为:每次请求都向服务器验证 Last-Modified/ETag,响应 304 时复用本地缓存)

安全头

add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

性能评估

构建性能

指标实测值参考基准评级
总构建时间3.22s<5s(良好)✅ 良好
平均每页耗时19ms
Vite 构建1.48s<2s(良好)
图片优化3ms(缓存)

171 个页面的静态站点在 3.22 秒内完成构建,适合频繁本地开发和 CI/CD 流程。GitHub Actions 部署流程(deploy.yml)中,npm ci + npm run build + rsync 通常在 30–60 秒内完成(含依赖安装)。

线上加载性能

指标实测值参考基准评级
TTFB0.183s<0.3s(良好)
首页加载0.219s<0.5s(良好)
Gzip 压缩率77.5%>70%(良好)
  • TTFB 低于 200ms,表明服务器处理请求 + 建立连接的开销很低
  • Gzip 将 HTML 从 42KB 压缩到 9.4KB,减少 77.5% 传输量
  • /_astro/ 下的 JS/CSS 文件带哈希 + immutable 标记,首次访问后不再产生网络请求

潜在优化方向

当前性能已满足需求,以下为可选的进一步优化:

1. 启用 Brotli 压缩(优先级:低)

Brotli 比 Gzip 压缩率约高 15–20%,几乎所有现代浏览器(覆盖率 >97%)支持。OpenResty 需安装 ngx_brotli 模块:

brotli on;
brotli_comp_level 6;
brotli_types text/plain text/css application/javascript
             application/json image/svg+xml;

预期收益: 首页 HTML 从 9.4KB → ~7.5KB(压缩后) 成本: Brotli 压缩比 Gzip 慢约 30%,但静态文件可预压缩(brotli_static on),首次命中后无 CPU 开销

2. HTTP/2 Push 或 Early Hints(优先级:低)

当前 Nginx 配置只监听 80 端口(HTTP/1.1),如果启用 HTTPS + HTTP/2,可利用多路复用减少并行资源加载时的连接开销。但当前页面 JS/CSS 资源极少(首页仅加载 19KB 的 hoisted JS),HTTP/2 的边际收益有限。

3. astro-compress 集成(优先级:低)

项目中已安装 astro-compress(devDependencies),当前未集成到构建流程。启用后可:

  • HTML 压缩(移除空白和注释)
  • CSS 压缩
  • 预估产物体积减少 5–10%

4. CDN(优先级:中)

当前服务器位于中国大陆,无 CDN。若站点有海外读者,可接入 CDN(Cloudflare、国内 CDN 等)减少跨地域延迟。当前页面已正确处理缓存头,对 CDN 友好。

数据验证清单

文章声明来源状态
Astro 6.3.1 版本package.json 第 31 行
npm run build 执行 astro buildpackage.json scripts.build
assetsInlineLimit: 0astro.config.mjs 第 75 行
构建日志(3.22s 等)2026-05-29 实际 npm run build 终端输出⚠️ 本文撰写时已记录,重写时在 WSL 环境无法复现
dist/ 总大小 15Mdu -sh dist/
文件总数 278find dist/ -type f | wc -l
HTML 页面 171find dist/ -name "*.html" | wc -l
博客页面 51find dist/blog/ -name "*.html" | wc -l
标签页面 112find dist/tags/ -name "*.html" | wc -l
_astro/ 81 个文件 1.5Mfind dist/_astro/ -type f | wc -l + du -sh
index.html 43009 bytesls -la dist/index.html
gzip_comp_level 5deploy/nginx/blog.misaka-net.top.conf 第 15 行
/_astro/ 缓存 1 年 + immutable同上,第 28–30 行
RSS/search 缓存 1 小时同上,第 34–35 行
astro-compress 已安装package.json devDependencies