Record curl/browser before-after metrics, mark U2 done, and release the integration slot while leaving U1/U3–U7 open. Co-authored-by: Cursor <cursoragent@cursor.com>
5.5 KiB
首次加载 U2:字体自托管与静态资源交付 测试报告
一、 测试背景 (Background)
诊断确认 8080 登录页下载约 2.82 MB 未压缩 JS,且 Google Fonts 外链 CSS 可阻塞首屏;Go serveSPA 无压缩协商、无明确缓存头,且缺失 /assets 会回退 HTML。本轮实施 U2(自托管字体、构建期预压缩、静态交付协商与 404 修复),不包含 U3 拆包。
二、 测试目标 (Test Objectives)
- 登录页无
fonts.googleapis.com/fonts.gstatic.com请求;阻断该域名仍可出现登录表单 - 主 JS 响应带
Content-Encoding: br或gzip,传输体积显著下降 /assets/missing.js→ 404 且 body 非 HTML- HTML
Cache-Control: no-cache;/assets//fontsimmutable;API 无 public 长缓存 - 单元测试与
go test -short/npm test通过
三、 测试方案与环境 (Test Plan & Environment)
- OS:Linux;Go 1.27.1;dev 容器
shuimu-agent-app-dev(镜像agent-dev-app@sha256:2d74fe18…) - 入口:
http://127.0.0.1:8080(构建产物) - 层级:Go 单元测试(
static_assets_test.go)、前端断言、curl 协商验收、Playwright Docker(mcr.microsoft.com/playwright:v1.63.0-noble)浏览器探针 - 代码:
dev@bc01781(mergefeature/initial-load-perf-u2);无缓存重建后镜像含/fonts与.br/.gz
四、 预期结果 (Expected Results)
| 场景 | 预期 |
|---|---|
Accept-Encoding: gzip, br |
Content-Encoding: br,主 JS ~624 KiB |
仅 gzip |
Content-Encoding: gzip |
identity / gzip;q=0 |
无 Content-Encoding,原始体积 |
/assets/missing-hash.js |
404,非 HTML |
| HTML / SPA fallback | Cache-Control: no-cache |
| 字体域名阻断 | 登录输入框仍可见 |
| API 未认证 | 401,无 immutable |
五、 实际测试结果与判定 (Actual Results & Evaluation)
5.1 单元测试
-
Input:
go test -short ./internal/server/ -run 'TestStaticAssets_|TestParseAcceptEncoding' -
Actual:
ok -
Verdict: PASS
-
Duration: ~0.66 s
-
Input:
npx tsx --test src/styles/noExternalFonts.test.ts;npm test -
Actual: 字体断言 2/2 PASS;前端套件 380 + vitest 32 PASS
-
Verdict: PASS
5.2 curl 协商(8080,无缓存重建后)
证据:.doc/test-reports/assets/2026-09-17-initial-load-perf-u2/after-curl-nocache.txt
| 检查项 | 实际 | 判定 |
|---|---|---|
| HTML | Cache-Control: no-cache,Vary: Accept-Encoding,无 Google Fonts |
PASS |
JS + gzip, br |
Content-Encoding: br,下载 623,898 B(原 2,820,055 B,−77.9%) |
PASS |
JS + gzip |
Content-Encoding: gzip,immutable |
PASS |
| JS identity | 无 encoding,Content-Length: 2820055,仍有 Vary |
PASS |
/assets/missing-hash.js |
404 404 page not found |
PASS |
/fonts/inter-v20-latin.woff2 |
200,immutable,48256 B,无 Content-Encoding |
PASS |
/sessions/demo |
200 + index,no-cache |
PASS |
/api/v1/chat/sessions |
401 JSON,无 immutable | PASS |
5.3 浏览器探针
证据:assets/2026-09-17-initial-load-perf-u2/browser-u2.json
| 场景 | 登录可见 | transferBytes | 外链字体请求 | 判定 |
|---|---|---|---|---|
| login-cold | 205 ms | 681,964 | 0 | PASS |
| login-font-domain-blocked | 213 ms | 681,964 | 0 | PASS |
对比诊断 before(同机冷缓存登录页):可见 ~662 ms,transferSize 2,857,761 B;主 JS 未压缩 2,820,055 B。本轮未登录首屏传输量下降约 76%。
主 JS Resource Timing:transferSize=624198,decodedBodySize=2820055(确认浏览器实际收到 br 变体)。
5.4 重启时间线(U7 起点证据,非 U7 完成)
| 事件 | 时刻 (UTC) |
|---|---|
| 容器 StartedAt | 2026-09-17T08:22:48.548Z |
| goose no migrations / kb online | 08:22:48.660–.676 |
| 日志「监听地址」 | ~08:22:48.7 |
| health=200 | ≤08:22:50(重建后首次探测) |
app restart → listen ≈ 150–200 ms(DB 已就绪、无迁移)。不能据此宣称用户「整机重启十几秒」已解决。
首次 env-service.sh dev rebuild 曾因并行 Agent 切走工作树导致镜像装入旧 web/;随后在 dev 上 docker compose build --no-cache app 后验收通过。证据见 rebuild-nocache-log.txt。
5.5 SSE
未认证 GET /api/v1/chat/stream 立即 401 JSON;静态压缩路径不触及 API/SSE。PASS(静态层无缓冲回归迹象)。
六、 自动化测试套件汇总 (Test Suite Execution)
go test -short ./internal/server/ -run 'TestStaticAssets_|TestParseAcceptEncoding' → ok
npm test (web) → 380 + 32 PASS
npm run build → precompress 49 .br / 49 .gz
未在本报告将 stub 输出当作交付证据;浏览器与 curl 均打真实 8080 容器。
七、 测试结论与后续优化建议 (Conclusion & Next Steps)
- U2 达到合并/dev 验收标准:字体去阻塞、压缩协商、缓存头、assets 404 均有真实证据。
- 不宣称 Success Criteria 全表达标(U1 登录态套件未建;U3 拆包未做,首屏 JS 解码体仍约 2.8 MB)。
- 后续:U3 懒加载;U1/U7 补齐重启与登录态预算;并行 Agent 占用主仓时,合入容器重建须
--no-cache或锁定工作树以免 BuildKit 读到脏上下文。
提交与环境
- 分支:
feature/initial-load-perf-u2→ 已merge --no-ff入dev@bc01781 - 镜像:
agent-dev-appsha256:2d74fe184585ec0d0d24a051cd6bbc0cfb5b2ef050a376a32027c8e442703cd1 - 资源:
/assets/index-Bu0CqZB_.js+.br - 未推送、未晋升 test/main