第 2 章 · 性能预算与无障碍实战
考点梳理
2.1 Core Web Vitals(“3 指标 + 预算”)
| 指标 | 含义 | 良好(示例预算) | 差(红线) |
|---|---|---|---|
| LCP | 最大内容元素渲染时间 | ≤ 2.5s | > 4s |
| INP | 交互到下一帧渲染 | ≤ 200ms | > 500ms |
| CLS | 累计布局偏移 | ≤ 0.1 | > 0.25 |
预算分配法(“L2 加分”):
总预算 LCP 2.5s
├── 网络传输(0.8s) → 压缩/CDN/HTTP2
├── 下载后执行(0.6s) → 代码分割/减依赖
├── 渲染阻塞(0.5s) → CSS 内联关键/字体策略
└── 余量(0.6s) → 缓冲
记忆锚:“LCP 二点五 INP 二百 CLS 一毛;先测再拆预算,超预算砍最大的”。
2.2 前端性能 5 招(“按收益排序”)
| # | 招 | 做法 | 典型收益 |
|---|---|---|---|
| 1 | 减首屏 JS | 路由级 lazy() + 首屏外组件动态 import | LCP ↓ 30%+ |
| 2 | 图片 | 正确尺寸(别传 4K 原图)+ 现代格式(AVIF/WebP)+ loading="lazy" | 流量 ↓ 50%+ |
| 3 | 字体 | font-display: swap + 子集化(中文按需分包) | 文字闪现 |
| 4 | 长任务拆分 | 大计算分片 / Web Worker(主线程别卡 > 50ms) | INP ↓ |
| 5 | 依赖治理 | bundle analyzer 找大依赖,换轻量替代 | 体积 ↓ |
流式输出场景专项(“AI 产品高频坑”):
| 坑 | 现象 | 对策 |
|---|---|---|
| 每 token 全量重渲染 | 打字卡顿(INP 爆) | 消息列表虚拟化(只渲染可见)+ 攒批更新(每 2~3 帧或每 30ms 刷一次) |
| 光标跳动 | 布局偏移 | 预留高度/固定行高(CLS) |
| 停止按钮卡死 | 点了没反应 | AbortController 真正中断请求(“假停止 = 假体验”) |
铁律:“流式场景 INP 是生命线——用户一边看输出一边想打字,卡了 = 产品不可用”。
2.3 无障碍 4 项实操(“4 项”)
| 项 | 检查方式 | 不合格示例 |
|---|---|---|
| 语义 | 标签语义对(button 不是 div onClick;label 关联输入;nav/main 地标) | 全 div 堆出来的"按钮"(读屏读不出) |
| 键盘 | 只用 Tab/Shift+Tab/Enter/Space 走完整流程 | AI 停止按钮 tabIndex 到不了 |
| 焦点 | :focus-visible 可见 + 顺序合理 | 焦点是默认细框看不见 |
| 对比 | 文本 ≥ 4.5:1(大字 3:1) | 灰字 #999 on #fff ≈ 2.8:1 |
键盘走查 5 步(“10 分钟做完”):
① Tab 到搜索框 → 输入 → Enter(能提交?)
② Tab 走表单 → 每个输入框 label 能读出来?
③ Tab 到 AI 停止/重试按钮 → Space 能触发?
④ 模态框打开后焦点是否被"锁"在里面?关闭后焦点回到触发按钮?
⑤ 页面跳转后焦点回到顶部?
AI 产品无障碍清单(“高频扣分点”):
- 流式输出的停止按钮键盘可达(“这是 AI 产品特有项”);
- 结果可复制/可编辑(读屏用户要能改);
- 错误提示不只靠颜色(红字 + 文字"失败"双通道);
- 骨架屏/加载态有
aria-live(读屏能播报"正在生成")。
记忆锚:“语义焦点对比键盘,四点五是线;AI 加两条:停止可 Tab,状态能播报”。
🧠 记忆工具箱
口诀速记
- 指标:“LCP 二点五 INP 二百 CLS 一毛”;
- 五招:“分割懒图字体换,长任务丢 Worker,依赖砍一砍”;
- 流式:“虚拟化攒批刷,预留高度别跳,停止要能真中断”;
- 无障碍:“语义焦点对比键盘,四点五是线;AI 加停止可达 + 状态播报”。
场景锚点
- 性能预算想象"“修路”":你不是司机(不需要赶路),你是"修路的"——“LCP = 从家到目的地总时长(2.5 分钟内);预算分配 = 每段路限时(哪段超了就修哪段);代码分割 = 别在市区建超宽大道(首屏只修需要的路段);长任务拆分 = 别让一辆大货车堵死三车道(主线程别卡)”——“修路不是越宽越好,是按预算把最堵的段先修好”。
- 无障碍想象"“餐厅给轮椅顾客设计动线”":你不是顾客(不需要吃饭),你是"无障碍设计师"——“键盘 = 轮椅(只能走通道,按钮必须在通道上);焦点可见 = 轮椅能’看见’自己到哪了;对比度 = 菜单字够大够清楚;语义标签 = 菜单按’凉菜/热菜’分区(读屏像’按区找菜’)”——“只考虑步行顾客的设计 = 一半客人进不来”。
⚠️ 易错提醒
- 性能"只优化首屏" = 不够:“INP 看交互,流式输出时打字不能卡”(“AI 产品 INP 权重更高”);
- “停止按钮假中断” = 体验事故:“AbortController 真中断,或至少 UI 立即响应”(“点了没反应 = 用户以为坏了”);
- 无障碍"补 alt 就完事" = 不及格:“键盘走查 + 焦点 + 对比度全过才算”(“评审会真的用键盘点一遍”);
- CLS"图片没给宽高" = 经典来源:"
width/height或aspect-ratio必须给"。