本文记录 2026-08-03 完成的页面加载性能优化、关键架构约束和后续回归标准。生产构建体积会随依赖版本和业务代码变化,本文数据用于保留同口径基线。
| 指标 | 优化前 | 优化后 | 变化 |
|---|---|---|---|
| 首页 JavaScript(gzip) | 353,499 B | 315,067 B | -10.9% |
| 文章详情客户端引用(raw) | 8,533,843 B | 574,479 B | -93.3% |
| Markdown 服务端化后的文章客户端引用(raw) | 6,969,562 B | 574,479 B | -91.8% |
公开文章不再向浏览器发送约 1.46 MB 的 Markdown 解析与高亮实现,也不再发送原先约 6.39 MB raw / 1.98 MB gzip 的拼音字典分块。优化后的生产客户端资源中不得出现 pinyin 实现。
- Markdown 正文、GFM 表格、代码高亮、标题锚点和 HTML 清理在服务端完成,初始 HTML 必须包含可阅读正文。
- 客户端只保留代码复制、展开/收起和文章选区复制等必要交互,不能让整个 Markdown 树跨越 Client Component 边界。
- 评论查询通过
Suspense流式加载,不阻塞文章正文和侧栏输出。 - 文章详情直接使用数据库保存的标签名称与 slug 构造链接,不在请求期间重复执行拼音转换。
pinyin只能由src/server/slug.ts引入,该模块必须声明server-only。- 文章创建、更新和标签管理由服务端生成最终 slug,客户端表单只提交用户显式填写的别名或空值。
- 已保存文章的图片上传使用只读
public_id作为目录名;尚未首次保存的新文章回退到blog/YYYY/MM,文件名继续使用 UUID 保证唯一。 - 不得修改既有文章和标签 slug,也不得因性能优化改变公开 URL。
- 页面转场、站点加载器和精选文章描边使用 CSS 动画,并遵循
prefers-reduced-motion。 - 设置弹窗和文章预览按需加载,可在用户悬停或聚焦入口时预取。
- 首页视频仅预加载当前首要资源,其余视频在首帧缓冲完成并进入空闲时段后加载。
/videos与/images静态资源使用可重验证的长期缓存响应头。
- 新上传的静态封面由服务端生成最长边不超过 3840px、质量 82 的 WebP 源文件;不放大小图, 多帧媒体与正文图片保持原文件,处理失败回退原上传行为。
- ImgBed、Supabase 公共存储、GitHub 头像和限定路径的 Bing 图片使用 Next.js 响应式优化;
优化请求失败时自动回退原 URL;未知外部主机直接使用
unoptimized兼容路径,不允许任意 服务端图片代理。 - 图片优化缓存最短 7 天,Supabase UUID 文件使用一年缓存且禁止覆盖。
max-w-6xl文章网格按移动端 35%、平板双列和桌面三列声明准确sizes;仅第一张卡片 封面预加载,其余图片保持懒加载。- 文章详情背景继续高优先级加载并保留原有
object-cover、模糊遮罩和明暗主题效果, 可信来源由图片优化器输出视口匹配尺寸。
提交涉及路由、Server/Client 边界或资源加载的改动时,至少执行:
npm run lint
npm run typecheck
npm test
npm run build
git diff --check生产构建后还需检查:
.next/static/chunks中不存在拼音词典或pinyin客户端实现。- 文章初始响应包含正文、表格和高亮代码,不依赖客户端解析后才可阅读。
- 首页、文章列表、搜索、标签和文章详情没有页面级横向溢出或控制台错误。
- 桌面端与移动端的明暗主题、代码复制、代码展开/收起和标签跳转保持正常。
- 后台文章保存和标签管理继续由服务端生成安全 slug;封面与编辑器图片使用文章数字标识目录,不依赖标题或 slug。
- 托管封面使用
/_next/image且不以列表卡片请求多兆字节源图;首屏列表只有第一张封面 预加载,折叠线下封面保持懒加载。 - 静态封面上传后为受控 WebP;正文图片、多帧动画、既有封面 URL、裁剪位置和页面布局 保持兼容。