主题
速度优化追踪
跟踪 WellChina 生产域名
wellchina.top在每次优化迭代前后的真实浏览器指标。 配套文档:速度优化方案(架构 / 决策 / 待办)· 全球可访问性与性能监控方案 起始基线:2026-04-28,Vercel Hobby 计划(function 锁iad1)。
量测方法
每个 baseline / iteration 都用同一套口径取数:
| 维度 | 工具 / 来源 | 备注 |
|---|---|---|
| LCP / TTFB / CLS / FCP / TBT / SI | WebPageTest(Milan iPhone 15 Chrome 4G) | 主基线测点;4G = 9 Mbps / 170 ms RTT |
| Lighthouse 分(A11y / BP / SEO) | Chrome DevTools MCP lighthouse_audit | mode=navigation, device=mobile |
| Vercel Function Region | 响应头 x-vercel-id 第二段 | 例:hkg1::hnd1::... 表 edge HK / function Tokyo |
| Vercel Edge Cache | 响应头 x-vercel-cache | HIT / MISS / STALE / PRERENDER |
| 探针位置 | 响应头 x-geo-city / x-geo-country | — |
当前状态(截至 2026-05-07)
| 指标 | 当前值 | Google CWV 阈值 | 等级 |
|---|---|---|---|
| LCP | 2.426 s | < 2.5 s = Good | 🟢 Good |
| CLS | 0 | < 0.1 = Good | 🟢 Good |
| TBT | 48–83 ms | < 200 ms = Good | 🟢 Good |
| TTFB | 1.536 s | < 600 ms = Good | 🟡 NI(cold cache 时) |
| FCP | 2.325 s | < 1.8 s = Good | 🟡 NI |
| Speed Index | 2.584 s | < 3.4 s = Good | 🟢 Good |
TTFB / FCP 仍 NI 是 WPT first-view(cold cache)数据。真实重复访问 + warm POP 应 < 200 ms。
x-vercel-cache: PRERENDER已确认首页是边缘静态化提供。
迭代序列
| 日期 | 改动 | LCP | TTFB | CLS | Commit |
|---|---|---|---|---|---|
| 2026-04-28 | Baseline(Hobby, function iad1)· WPT Milan 4G | 6.878 s | 5.981 s | ~0.186 | bc1d59a |
| 2026-05-06 | function 迁 hnd1(Pro 计划) | 5.313 s | 1.701 s | 0.186 ⚠️ | 2ce6e48 |
| 2026-05-06 | font-display: optional + 146 张图搬 /public/ | 3.006 s | 1.591 s | 0 ✅ | 4128c62 + a92a03e |
| 2026-05-07 | Layout 移 client + 首页边缘缓存 | 2.426 s ✅ | 1.536 s | 0 | c8d1fdf + 562f3b9 |
| 累计 Δ | — | −4.45 s / −65% | −4.45 s / −74% | −100% | — |
每次改动的具体内容见 speed-optimization-plan / 已完成的工作。
各阶段关键观察
function 迁 hnd1(2026-05-06)
单一改动 = function region iad1 → hnd1。其他变量未动。
- TTFB 暴跌 72%(5.98 → 1.70 s):function ↔ DB 同区域(hnd1 ↔ ap-northeast-1)的预期收益完全兑现。
x-vercel-id: hkg1::hnd1::...确认 function 部署到东京。 - LCP 仅降 23%:因为 LCP - TTFB = 3.6 s 渲染阶段。Hero 图来自 Supabase Tokyo 跨大陆 + Web font swap 仍在拖。
- CLS 0.186 新观测:基线没记 CLS,本次首次量到。不是 hnd1 引入的——是字体 swap 一直存在的问题。
CLS 修复 + 静态图本地化(2026-05-06)
CLS 0.186 根因诊断(代码层排查):
- ✗
<Image>全部 fill in fixed-height containers (h-24/h-32/py-28) — 不会 shift - ✗ Logo / avatar 用 explicit
width×height— 不会 shift - ✗ Framer Motion
AnimatedSection/StaggerItem用 transform translateY — transform 不计入 CLS - ✗
ConsentBannerposition: fixed— 不影响 document flow - ✗
GeoAdvisoryBannerSSR 渲染(首访 Milan 命中 advisory,无 dismiss flash) - ✓
/public/fonts/fonts.css内 28 个@font-face全部font-display: swap— Lora / Source Sans 3 加载完后替换 fallback Georgia/system-ui,metrics 不同 → 文字行高变化 → 后续内容位移
修复:把 28 个 font-display: swap 改 optional。optional 行为:浏览器给 web font 100 ms block 期,到点没下载完就永远不替换整个 session 用 fallback。代价:慢网首访看不到 Lora / Source Sans 3,但零 CLS 风险。
静态图搬 /public/(146 张 / 19.3 MB)的核心收益:
/public/site-assets/brand/hero-bg.webp从 Vercel POP 直出(< 100 ms)替代了 Supabase Tokyo 跨大陆拉取(300-500 ms)。这是 LCP -2.3 s 的主要来源。- 用户体验决策(频繁切医院):放弃 Cloudflare 反代 Supabase 方案,全 146 张直接搬
/public/—— 零 cold-miss,体验严格更优。
边缘缓存(2026-05-07)
部署后用 curl 验证:
curl https://www.wellchina.top/反复 5 次,response 头age持续递增(17 → 19 → 20 → 21 → 23)- content-length 完全一致 215186 字节
x-vercel-cache: PRERENDER(build-time 预渲染)x-vercel-id仅hkg1::edge POP 段,没有 function region 段 —— 请求根本没去 function 跑
Build 修复(旅程中遇到的失败)
移除 root layout 的 getLocale() 后,next.js 把所有页都标 static-friendly,结果 build 时试图静态化 admin/account/sitemap → prisma 连接打爆 Supabase pooler。修复了三件事:
admin/(dashboard)/layout.tsx加export const dynamic = 'force-dynamic'[locale]/account/page.tsx+[locale]/account/orders/[id]/continue/page.tsx加force-dynamicsitemap.ts加force-dynamic,并在next.config.ts给/sitemap.xml加 24h CDN cache headerlib/prisma.ts检测NEXT_PHASE === 'phase-production-build',build 期间connection_limit从 10 降到 2(4 workers × 2 = 8 < Supabase pooler 上限 15)
验收门槛
每次优化 PR 合并后必须在 24h 内重测;如果出现以下情况之一,回滚 PR:
- 任一路径 LCP 比上一基线 +200 ms 以上
- Lighthouse A11y / BP 降 ≥ 3 分
- WPT Milan 重测 LCP > 8 s → 立即排查
- 任意页面
x-vercel-cache: HIT比例下降(说明 cache 被破坏)
每完成一个步骤,按同口径重测:WPT Milan iPhone 15 4G + Speed Insights RUM。
历史快照原始文件
trace JSON / lighthouse HTML 报告归档到 docs/data/performance-baselines/(暂未建,首次需要时 mkdir -p),命名 YYYY-MM-DD-{path}.{json|html}。