关于 frontend-performance
frontend-performance 是帮助前端开发者审计和优化网页性能的技能,强调先测量再诊断,并以 WebKit/Safari 优先验证,同时区分 Chromium 实验室数据与真实用户数据。
主要功能
- 01分阶段性能审计流程
- 02WebKit/Safari 优先测试
- 03Core Web Vitals 与测量说明
- 04JavaScript、CSS、图片和缓存优化指南
- 05CSP 与无障碍检查
适用场景
- 01排查 Lighthouse 或 PageSpeed 指标问题
- 02验证 Safari 与 Chromium 的性能差异
- 03依据性能跟踪定位资源瓶颈
- 04优化页面加载并检查无障碍回归
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ ssheleg/ sheleg-dev --skill frontend-performance安装后在 Claude Code 中输入/frontend-performance确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/accessibility-perf.mdcss-performance.mdnextjs.md详细介绍
前端性能
优化前端应用,以获得尽可能高的 Lighthouse 分数和真实用户性能。本技能涵盖技术性能层面——外观方面请参阅 sheleg-design;界面必须实现的功能请参阅 super-ux。
审查工作流
- 测量——运行 PageSpeed Insights 或 Lighthouse(Chromium),并先在 WebKit 中加载相同场景(见下文 测试浏览器)。记录分数、未通过的审查项,以及每个数据所用的引擎。
- 诊断——将每个未通过的审查项对应到具体的代码层面原因(见下方检查清单)。
- 确定优先级——按影响程度修复:P0 会阻止渲染,P1 会影响指标,P2 仅提供参考信息。
- 实施——按照参考指南应用修复。
- 验证——运行
next build(或框架对应的命令),然后重新运行 Lighthouse 和 WebKit 测试。确认两个引擎都没有出现回归。
测试浏览器——优先使用 WebKit(Safari)
优先在 WebKit 中加载页面并分析性能:使用 Safari 和
safaridriver(WebDriver;执行一次 sudo safaridriver --enable)来测试真实浏览器;使用 Playwright 的
webkit(webkit 项目、--browser webkit,通过
npx playwright install webkit 安装)运行脚本和生成跟踪记录;使用 Safari Web
检查器中的 Timelines 进行调试。在 macOS 上,使用
open -a Safari <url> 打开页面,而不要使用系统默认浏览器,因为它可能采用其他
引擎。自动化库(如 browser-use)有 WebKit/Safari 后端时,应使用该后端。三大引擎中,WebKit 的支持范围最窄——只有 iOS Safari 用户才会遇到的回归问题,对下文列出的所有 Chrome 工具来说都不可见。
Lighthouse、PageSpeed Insights、CrUX、CDP 跟踪记录和 chrome-devtools MCP 都是基于 Chromium 的——它们仍可用于此工作流,但必须明确说明这是 Chromium 例外:当任务需要 Chrome 本身时使用,并说明使用了哪些工具以及原因。启动 Chrome 测试时,优先使用 Chrome Dev 版本;为其指定一个临时配置文件(绝不使用用户的配置文件),记录启动的内容,并在结束前关闭所有已启动的进程。只在 Chromium 中检查过的页面,应报告为“仅在 Chromium 中检查过”,绝不能说“已在浏览器中测试”;Lighthouse 分数是 Chrome 实验室数据,并非跨浏览器结论。
Core Web Vitals,以及与之相关的诊断指标
这是两个相互独立的维度,把它们混为一谈是常见错误。 第一个维度: 它是不是 Core Web Vital——也就是 Google 报告并用于排名的指标(LCP、INP、CLS) ——或者不是。第二个维度:在哪里可以测量它——在 FIELD(真实用户, CrUX)中,还是只能在 LAB(合成测试)中。这两个维度并不重合:一个指标 可以不是 CWV,却仍然能在真实用户环境中测量。FCP 就打破了只有一个维度的说法——它不是 Core Web Vital,却可以在真实用户环境中测量 (CrUX 会报告 FCP;web.dev 列出了 FCP 的实验室和真实用户环境工具)。先前关于“只有三个 CWV 能在真实用户环境中测量”的说法是错误的。
| 指标 | 是 Core Web Vital? | 可在真实用户环境中测量? | 良好 | 需要改进 | 较差 |
|---|---|---|---|---|---|
| LCP | 是 | 是(CrUX) | < 2.5s | 2.5-4.0s | > 4.0s |
| INP | 是 | 是(CrUX) | < 200ms | 200-500ms | > 500ms |
| CLS | 是 | 是(CrUX) | < 0.1 | 0.1-0.25 | > 0.25 |
| FCP | 否 | 是(CrUX) | < 1.8s | 1.8-3.0s | > 3.0s |
| TBT | 否 | 否(仅限实验室) | < 200ms | 200-600ms | > 600ms |
| SI | 否 | 否(仅限实验室) | < 3.4s | 3.4-5.8s | > 5.8s |
真实用户环境的指标声明必须始终附带其数据来源信息:p75(Google 用于分类的第 75 百分位数,绝不是平均值)、设备/群体(手机还是桌面设备,以及对应的用户群体)、时间段(CrUX 使用过去 28 天的滚动窗口),以及样本量(数据量不足的来源没有真实用户数据——这意味着unknown,而不是good)。缺少这四项的数字,就是冒充真实用户数据的实验室数据。
TBT 是与 INP 相关的诊断性 CORRELATE 指标,绝不能替代 INP 的证据。 实验室测试中的 TBT 良好,可以提示 INP 可能表现不错;但它不能证明 INP 表现良好,因为 INP 是通过实验室未执行的真实交互来测量的。因此,如果某个页面有 CrUX FCP 数据和 Lighthouse TBT,却没有真实用户 INP,报告应写明 FCP = 有真实用户数据支持,INP = 未知——绝不能说“TBT 证明 INP 已通过”。告诉客户他们的 Speed Index 是不合格的 Core Web Vital,就是在说一个 Google 并不用于排名的指标;因为 TBT 表现良好就告诉客户 INP 已通过,则是在宣称一项根本没人测量过的结果。
阈值和分类已根据 web.dev/articles/vitals 核实,日期为 2026-08-16。
性能检查清单
字体(LCP、FCP)
- 自行托管字体 -- 绝不要通过
<link>标签从外部 CDN 加载。使用框架的字体优化功能(next/font/google、@fontsource等),将 CSS 内联并自行托管字体文件。 - 预加载关键字体 -- LCP 元素所用的字体必须尽早加载。
- 限制字体系列数量 -- 最多 3 个系列。每个系列会增加约 20-50KB。
- 对子集字体进行加载 -- 仅加载所需的字符集(
latin、latin-ext)。 - 使用
font-display: swap-- 防止加载期间文本不可见(FOIT)。 - 移除未使用的预连接 -- 如果字体由自行托管,则连接到字体 CDN 的
preconnect毫无作用。
进行上述任何更改之前:先测量,不要直接开方。 以下项目是优化经验法则,并非一刀切的规则——每项都必须有证据支持,盲目照搬可能会为了分数牺牲功能。进行任何更改前,先检查三项:性能跟踪记录和使用场景(低端设备在慢速网络下实际需要等待什么)、浏览器支持约定(页面必须继续支持哪些用户),以及无障碍负责人(页面结构由他们负责,而不是由分数决定)。只有在验收标准涵盖以下内容时,才能发布更改:低端设备/慢速网络场景、键盘操作和标题结构保持不变、仍支持既定浏览器矩阵、没有新增未经批准的 CSP 来源,以及多次可比的前后测量均显示有所提升,且功能没有任何损失。
JavaScript(TBT、FCP、LCP)
- 根据实测瀑布流拆分代码——延迟加载追踪显示首屏绘制不需要的内容;“初始包中只有 Hero 和导航”只是一个初始假设,并非规则——场景需要在首屏显示的区块应保留,无论分数如何。
- 延迟加载第三方脚本——GA、分析工具、聊天组件应在交互后加载(
afterInteractive或defer)。 - 针对用户使用的浏览器——
browserslist应遵循明确的用户支持政策(你的分析数据、你的合同),而不是默认使用“最近 2 个版本”。下面的last 2是一个示例;未经确认就直接发布,导致某些用户的浏览器不再受支持,只为节省一个 polyfill,这种做法不可取:# example only — replace with your measured support matrix last 2 Chrome versions, last 2 Firefox versions, last 2 Safari versions, last 2 Edge versions - 对导入进行摇树优化——当包分析器显示
import * as会引入无用代码时,优先使用命名导入;这只是摇树优化的辅助方法,并非禁令——如果测量结果显示命名空间导入没有成本,那就不算缺陷。 - 分析包体积——使用
@next/bundle-analyzer、source-map-explorer或vite-plugin-visualizer。
CSS 和动画(CLS)
- 动画仅使用合成属性——只对
transform和opacity(由 GPU 合成)添加动画。不要对background-position、width、height、top/left、margin、padding添加动画。 - 谨慎使用
will-change——仅对实际会动效的元素添加will-change: transform或will-change: filter。 - 内联关键 CSS——应由框架处理(Next.js 会自动处理)。
- 避免布局偏移——为图片和嵌入内容设置明确的
width/height。为动态内容预留空间。
图片(LCP、CLS)
- 使用
<Image>组件——经过框架优化的组件(next/image、Astro<Image>)会自动调整尺寸、转换为 WebP/AVIF 格式,并添加width/height。 - 优先加载 LCP 图片——为 Hero/LCP 图片添加
priority(Next.js)或fetchpriority="high"。 - 延迟加载首屏以下的图片——初始视口以下的所有图片都应设置
loading="lazy"。 - 尺寸预算:Hero < 200KB,缩略图 < 50KB,图标使用 SVG。
- 响应式
sizes——响应式图片始终提供sizes属性。
缓存(重复访问)
- 静态资源:对带哈希的文件(JS、CSS、字体、图片)使用
Cache-Control: public, max-age=31536000, immutable。 - HTML:使用
Cache-Control: public, max-age=0, must-revalidate(或框架默认值)。 - 验证匹配模式——针对实际 URL 测试缓存标头的
source匹配模式。常见错误:类 glob 模式({.svg,.png})在某些框架的路径匹配中不起作用(例如,Next.js 使用path-to-regexp)。应改用正则表达式参数语法:/:path*.:ext(svg|png|jpg|jpeg|gif|webp|ico|woff|woff2)
内容安全策略(最佳实践)
- 根据功能需要批准来源,而非为了分数——只有页面确实需要某个来源时,它才能加入 CSP,并且每个来源都应经过审核;为了消除控制台错误而将页面加载的所有来源都加入白名单,会为了一个最佳实践分数而牺牲 CSP 的全部意义。未经批准不得发布新的来源。
- 每次更改第三方内容后都进行审计——添加分析工具、字体或 CDN 脚本时,需要更新 CSP。
- 迁移后收紧策略——如果从外部字体迁移到自托管,应移除旧的 CSP 条目。
- 常见 CSP 来源:
- Google Analytics:
https://www.googletagmanager.com、https://www.google-analytics.com - Cloudflare:
https://static.cloudflareinsights.com - Stripe:
https://js.stripe.com
- Google Analytics:
无障碍(Lighthouse A11y 评分)
以下内容会直接影响 Lighthouse 无障碍评分:
- 对比度——WCAG AA 要求普通文本的对比度达到 4.5:1,大号文本达到 3:1。避免在文本颜色上使用透明度修饰符(例如,Tailwind 中的
text-primary/80会降低对比度)。请使用不透明度为 100% 的颜色令牌。 - 标题层级遵循由无障碍负责人确定的结构——按顺序使用
h1->h2->h3,不可跳级。只有在标题确实不是章节标题时,才将其降级为<p>;为了让 Lighthouse 审计结果好看,而把真正的页脚章节标题降级为<p>,会移除屏幕阅读器用户赖以导航的结构。此处应以无障碍为准,而非评分。 - 替代文本——与相同文本相邻的装饰性图片使用
alt=""。信息性图片应添加描述性替代文本。切勿重复相邻文本。 - 点击目标——移动设备上至少为 48x48px。适用于按钮、链接和表单输入框。
特定框架指南
- Next.js:有关
next/font、next/image、next/dynamic、next/script、next.config中的缓存标头、CSP 配置和打包分析,请参阅 references/nextjs.md。 - CSS/动画:有关合成规则、渐变动画替代方案、
will-change的用法和关键 CSS 策略,请参阅 references/css-performance.md。 - 无障碍:有关对比度计算、标题层级规则和影响 Lighthouse 的 ARIA 模式,请参阅 references/accessibility-perf.md。
常见 PageSpeed 问题及修复方法
| 审计项 | 原因 | 修复方法 |
|---|---|---|
| “消除阻塞渲染的资源” | 外部字体 CSS、大型 CSS 文件 | 自托管字体,内联关键 CSS |
| “减少未使用的 JavaScript” | 整个页面的打包文件预先加载 | 使用动态导入进行代码拆分 |
| “避免非合成动画” | 为 background-position、width 等属性设置动画 | 替换为 transform/opacity/filter |
| “使用高效的缓存策略提供静态资源” | 缺少或有效期过短的 Cache-Control 标头 | 为带哈希的资源设置 max-age=31536000, immutable |
| “背景色和前景色的对比度不足” | 文本颜色使用透明度修饰符 | 使用不透明度为 100% 的颜色令牌 |
| “标题元素顺序不连续” | 跳过标题级别(h1 -> h4) | 修正层级,或对非结构性标题使用 <p> |
| “浏览器错误已记录到控制台” | CSP 阻止脚本/样式 | 在 CSP 中将必需的来源列入白名单 |
| “图片元素缺少 [alt] 属性” | 缺少或冗余的替代文本 | 添加描述性替代文本;装饰性图片使用 alt="" |
| “避免关键请求链” | 阻塞资源形成瀑布流 | 预加载关键资源,并采用自托管 |
| “旧版 JavaScript” | 为现代 API 加载 polyfill | 更新 browserslist 目标 |
性能预算模板
为落地页设置以下限制:
| 资源 | 预算 |
|---|---|
| 页面总大小 | < 1.5 MB |
| JavaScript(压缩后) | < 200 KB |
| CSS(压缩后) | < 50 KB |
| 字体(总计) | < 150 KB |
| 主视觉图片 | < 200 KB |
| LCP | < 2.5s(移动设备) |
| FCP | < 1.8s(移动设备) |
| CLS | < 0.1 |
| TBT | < 200ms |
相关技能
sheleg-design——页面的外观与动效,包括本页面的数值预算所限定的动效预算super-ux——界面必须实现的功能,以及页面加载缓慢时会受影响的流程seo-aeo-audit——技术 SEO 与可抓取性;它从实际环境而非实验室中读取相同的 Core Web Vitals
这里曾列出的四个名称——frontend-design、landing-page-design、
next-best-practices、responsive-design——都无法解析到可安装的内容,而
seo-audit 只差一个字符类就能成为真正的 seo-aeo-audit,这就是错别字能通过审查的原因。
降级情况
- 不是 Claude Code(Cursor、Codex、skills CLI、API 容器):此工具包的
PreToolUsegate 不会运行——这里的每条规则仍然适用,只是由人而非钩子来执行。 - 没有浏览器通道(没有
safaridriver、Playwrightwebkit、Chrome DevTools MCP):页面评估依据是 差异,且本机未测量相关数值。请记录较弱的结论; 没有人实际运行的 Lighthouse 分数不算分数。 - 没有网络:PageSpeed Insights 和实测数据不可用。仍然值得基于实验室数据进行分析——说明你完成了哪一部分。
触发条件
更多会将请求导向此处的短语:“性能审计”、“LCP”、“CLS”、“INP”、“阻塞渲染”、 “代码拆分”、“延迟加载”、“缓存标头”、“速度优化”。
从 0.16.2 的描述中移至此处:“包体积”。