ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Lighthouse 插件开发实战:用 lighthouse-plugin-example 模板打造自定义审计

Lighthouse 插件开发实战:用 lighthouse-plugin-example 模板打造自定义审计 Lighthouse 插件开发实战用 lighthouse-plugin-example 模板打造自定义审计【免费下载链接】lighthouseAutomated auditing, performance metrics, and best practices for the web.项目地址: https://gitcode.com/GitHub_Trending/lig/lighthouse本指南基于 Lighthouse 官方提供的 lighthouse-plugin-example 插件模板完整讲解从零搭建一个 Lighthouse 插件的全过程包括三个核心文件的职责拆解、本地开发与迭代运行方式、面向插件使用者的安装与执行方法并结合仓库源码深入剖析插件配置的解析校验机制与自定义审计的编写规范。读完本文你将具备独立开发、调试并发布一个可共享的 Lighthouse 插件在报告中新增自定义审计类别的完整实战能力。Lighthouse 插件是什么Lighthouse 插件Plugin是一种扩展 Lighthouse 能力的方式它本质上是一个 Node 模块实现一组由 Lighthouse 执行、并以新增类别形式出现在报告中的检查项。插件非常适合领域专家例如 SEO、广告、可访问性团队把特定领域的检查逻辑沉淀成可复用的模块再通过 NPM 分享给其他 Lighthouse 用户。在动手之前需要先分清插件与自定义配置Custom Config的边界。插件易于共享、API 在 minor 版本之间保持稳定但作用范围也比自定义配置更受限。官方在 plugins.md 中给出了能力对照能力插件自定义配置引入自定义审计✅✅新增自定义类别✅✅易于在 NPM 上共享与扩展✅❌Semver 稳定的 API✅❌从页面采集自定义数据artifacts❌✅修改核心类别❌✅修改config.settings属性❌✅可见如果只是想在报告中加自己的审计和类别插件是首选而需要采集页面自定义数据或修改核心配置时应转向自定义 Lighthouse 配置。模板三件套从文件结构读懂插件形态Recipe 目录docs/recipes/lighthouse-plugin-example一共包含三个关键文件恰好构成一个最小可用插件的全部骨架package.json—— 声明插件的入口plugin.js与依赖关系plugin.js—— 指示 Lighthouse 运行插件自带的preload-as.js审计并描述报告中的新类别及其详情audits/preload-as.js—— 在 Lighthouse 默认审计之外新增的审计逻辑。下面逐一拆解这三个文件。package.json一个「名正言顺」的 NPM 模块插件的package.jsonpackage.json写法如下{ name: lighthouse-plugin-example, private: true, type: module, main: ./plugin.js, peerDependencies: { lighthouse: ^13.4.1 }, devDependencies: { lighthouse: ^8.6.0 } }要点有两处其一Lighthouse 通过插件名识别插件模块名必须以lighthouse-plugin-开头其二插件不应直接依赖 Lighthouse 作为运行时依赖而是用peerDependencies向使用方声明所需的 Lighthouse 版本用devDependencies供本地开发使用当前仓库模板里peerDependencies为^13.4.1devDependencies为^8.6.0实际开发时建议两者对齐。main指向的plugin.js就是插件配置的入口文件。plugin.js声明审计、类别与评分plugin.jsplugin.js是插件的配置核心它声明了要新增的审计、类别名称以及评分方式/** type {LH.Config.Plugin} */ export default { // Additional audit to run on information Lighthouse gathered. audits: [{ path: lighthouse-plugin-example/audits/preload-as.js, }], // A new category in the report for the new audits output. category: { title: My Plugin Category, description: Results for our new plugin category., auditRefs: [ {id: preload-as, weight: 1}, {id: meta-description, weight: 1}, // Can also reference default Lighthouse audits. ], }, };这个文件包含两个必需属性audits新审计的路径数组。每个路径应写成像使用者传给模块解析器那样的「绝对」形式即lighthouse-plugin-你的插件名/path/to/audits/audit-file.js对应类型为Array{path: string}。category新类别的展示信息与评分配置至少需要title和auditRefs两个属性。auditRefs中每一项是{id, weight, group?}weight决定该审计在整个类别得分中的权重。注意auditRefs里除了插件自己的preload-as还可以直接引用 Lighthouse 的默认审计如这里的meta-description这正是插件「复用核心审计能力」的体现。audits/preload-as.js自定义审计的实现样例audits/preload-as.jsaudits/preload-as.js是一个完整的自定义审计实现检查页面里所有link relpreload标签是否带有正确的as属性import {Audit} from lighthouse; // https://fetch.spec.whatwg.org/#concept-request-destination const allowedTypes new Set([font, image, script, serviceworker, style, worker]); class PreloadAsAudit extends Audit { static get meta() { return { id: preload-as, title: Preloaded requests have proper as attributes, failureTitle: Some preloaded requests do not have proper as attributes, description: link relpreload tags need an as attribute to specify the type of content being loaded., requiredArtifacts: [LinkElements], }; } static audit(artifacts) { const preloadLinks artifacts.LinkElements.filter(el el.rel preload); const noAsLinks preloadLinks.filter(el !allowedTypes.has(el.as)); const passed noAsLinks.length 0; return { score: passed ? 1 : 0, displayValue: Found ${noAsLinks.length} preload requests with missing \as\ attributes, }; } } export default PreloadAsAudit;一个审计类需要实现两个静态成员meta审计的元信息包括idkebab-case 字符串标识通常与文件名一致、成功与失败时的标题title/failureTitle、说明审计重要性的description支持 Markdown 链接以及requiredArtifacts本审计运行时必须存在的 artifacts 列表。这里声明了LinkElements即页面链接元素的采集产物。audit(artifacts)审计主逻辑接收artifacts键为requiredArtifacts中声明的产物返回score0 到 1以及可选的displayValue等展示信息。该审计从artifacts.LinkElements中筛出rel preload的链接再检查as属性是否落在 Fetch 规范允许的目标类型集合[font, image, script, serviceworker, style, worker]内只要有一个缺失或非法即判失败。从源码看LinkElements的来历该 artifact 由 core/gather/gatherers/link-elements.js 采集其getArtifact方法同时合并了来自 DOM 与 HTTP 响应头两路数据并统一将rel小写化方便下游审计消费见getLinkElementsInDOM与getLinkElementsInHeaders两条采集路径。这也解释了为什么审计里可以直接用el.rel preload做过滤。插件开发者视角从模板起步以 Recipe 为模板初始化项目把本仓库的 recipe 目录拷到自己的新项目里即可起步mkdir lighthouse-plugin-example cd lighthouse-plugin-example curl -L https://github.com/GoogleChrome/lighthouse/archive/main.zip | tar -xzv mv lighthouse-main/docs/recipes/lighthouse-plugin-example/* ./ rm -rf lighthouse-main注意上面的命令是从 GitHub 拉取 Lighthouse 主分支压缩包再解压提取在当前仓库内你可以直接以 docs/recipes/lighthouse-plugin-example 目录为模板复制。重命名插件时务必同步重命名其目录名插件名、目录名、audits中的模块路径三者需保持一致。只运行自己的插件安装依赖并单独运行插件yarn NODE_PATH.. npx lighthouse -- https://example.com --pluginslighthouse-plugin-example --only-categorieslighthouse-plugin-example --view这里NODE_PATH..是一个本地开发技巧把父目录加入 Node 模块解析路径让 Lighthouse 能解析到尚未发布的插件当插件从 NPM 安装为 node module 时不需要。关键 CLI 参数如下对应实现见 cli/cli-flags.js--plugins运行指定插件支持逗号分隔多个值array: truesplitCommaSeparatedValues--only-categories只运行指定类别内置类别如accessibility、best-practices、performance、seo等这里传入插件的类别名lighthouse-plugin-example--view运行结束后在浏览器中打开 HTML 报告。迭代开发采集一次、反复审计为避免每次改动审计逻辑都要重新打开浏览器采集可以拆成两阶段# 阶段一从浏览器采集 artifacts 并保存到磁盘 NODE_PATH.. npx lighthouse -- https://example.com --pluginslighthouse-plugin-example --only-categorieslighthouse-plugin-example --gather-mode # 阶段二反复重跑只做审计可加 --view 预览 NODE_PATH.. npx lighthouse -- https://example.com --pluginslighthouse-plugin-example --only-categorieslighthouse-plugin-example --audit-mode --view对应 cli/cli-flags.js 中的定义--gather-mode别名-G采集 artifacts 并保存到磁盘若未同时开启 audit-mode 则提前退出--audit-mode别名-A从磁盘读取已保存的 artifacts 进行处理未指定目录时默认取./latest-run/。这一「采集/审计分离」的工作流能显著缩短插件迭代的反馈周期。发布到 NPM迭代完成后npm publish或yarn publish将插件发布到 NPM供他人以普通依赖方式安装使用。插件使用者视角安装与运行作为插件用户而非开发者只需三步安装lighthousev5与插件lighthouse-plugin-example通常作为devDependenciesnpm install -D lighthouse lighthouse-plugin-example运行本地 Lighthouse 二进制有三种方式任选其一npx --no-install lighthouse -- https://example.com --pluginslighthouse-plugin-example --viewyarn lighthouse https://example.com --pluginslighthouse-plugin-example --view在package.json中新增一个调用lighthouse的 npm script 再执行。打开生成的 HTML 报告查看插件新增的「My Plugin Category」类别及其审计结果。深入源码插件配置如何被解析与校验插件plugin.js里的对象并不是直接塞给核心运行的而是经过 core/config/config-plugin.js 中ConfigPlugin.parsePlugin(pluginJson, pluginName)的严格解析与校验。理解这段源码有助于写出「一次通过」的插件配置入参防御先JSON.parse(JSON.stringify(...))深拷贝并去激活 live 属性再断言插件整体是一个普通对象多余的顶层键会抛出${pluginName} has unrecognized properties: [...]错误audits 解析_parseAuditsList允许缺省不新增审计时回退undefined但若提供则必须是对象数组且每个对象只能有path一个键path必须是字符串category 解析_parseCategorytitle必填且须为字符串或 ICU 消息description、manualDescription可选auditRefs必填且每项{id, weight, group?}都要通过类型校验其中group会被自动加上${pluginName}-前缀以命名空间隔离groups 解析_parseGroups可选键为 group ID、值为{title, description?}同样会统一加上插件名前缀避免与核心类别分组冲突supportedModes可选项必须是navigation、timespan、snapshot三种模式组成的数组缺省时表示类别支持全部模式。最终parsePlugin返回的配置结构为{audits, categories: {[pluginName]: {...}}, groups}即把插件类别挂载到以插件名为键的类别表中与核心类别并存。自定义审计的编写指南meta 字段约定meta是审计的元数据需覆盖以下字段id: string必填kebab-case 审计标识通常与文件名一致title: string必填审计通过时的简短可见标题failureTitle: string可选审计失败时的简短标题description: string必填说明审计重要性的详细描述支持 Markdown 链接requiredArtifacts: Arraystring必填审计执行所必需的 artifacts 列表scoreDisplayMode: numeric | binary | manual | informative可选分数展示方式的标识。audit(artifacts, context) 与可用 artifactsaudit()接收两个参数artifacts的键即requiredArtifacts中声明的产物context是内部对象主要用途是从DevtoolsLog派生网络请求信息。审计的核心目标是基于artifacts返回 01 的score。插件可稳定使用的 artifacts 包括fetchTime、BenchmarkIndex、settings、Timing、HostFormFactor、HostUserAgent、HostProduct、GatherContext、URL、ConsoleMessages、DevtoolsLog、MainDocumentContent、ImageElements、LinkElements、MetaElements、Scripts、Trace、ViewportDimensions。列表之外的 artifacts 被视为实验性产物结构随时可能变化应谨慎使用。处理网络请求网络请求的原始信息藏在DevtoolsLogartifact 中页面加载期间的全部 DevTools Protocol 流量审计时再派生请求对象import {Audit, NetworkRecords} from lighthouse; class HeaderPoliceAudit { static get meta() { return { id: header-police-audit-id, title: All headers stripped of debug data, failureTitle: Headers contained debug data, description: Pages should mask debug data in production., requiredArtifacts: [DevtoolsLog], }; } static async audit(artifacts, context) { const devtoolsLog artifacts.DevtoolsLog; // 传入 context 以便 Lighthouse 缓存派生结果避免每个审计重复计算。 const requests await NetworkRecords.request(devtoolsLog, context); const badRequests requests.filter(request request.responseHeaders.some(header header.name.toLowerCase() x-debug-data) ); return { score: badRequests.length 0 ? 1 : 0, }; } } export default HeaderPoliceAudit;最佳实践与常见误区命名规范类别标题短小少于 20 字符理想情况下是单个词或缩写避免加「Lighthouse」「Plugin」这类冗余前缀类别描述为插件审计提供上下文并链接到用户可进一步了解或提问的地方审计标题用现在时描述页面「做对了 / 做错了什么」。例如「Document has atitleelement」而非「Good job onaltattributes」审计描述简要说明审计为什么重要并用 Markdown 链接指向更详细的指南。评分要点按重要性为每个审计分配weight在单个审计内部用 01 之间的数值区分得分默认得分 0.9 会收进「Passed Audits」折叠区当审计不适用时返回{score: null, notApplicable: true}而不是硬给分。常见错误忘记过滤页面会存在各种边界情况——非网络请求blob:、data:、file:、非 JavaScript 脚本typex-shader/x-vertex等、跟踪像素图1x1、0x0 尺寸的图片等审计前务必考虑这些情况忘记归一化artifacts 通常如实反映页面观测值只按规范做最小归一化因此响应头名称/值、脚本type、脚本src等字段可能带空白、大小写混用、缺失或相对 URL处理时要自行归一化。运行结果模板中附带的截图 plugin-recipe-screenshot.png 展示了插件跑通后的报告效果新增的「My Plugin Category」类别出现在报告中示例得分为 50其中「Preloaded requests have properasattributes」审计通过提示Found 0 preload requests with missing as attributes同时复用的默认审计「Document does not have a meta description」作为失败项展示红色/绿色状态与折叠面板的呈现方式和 Lighthouse 内置类别完全一致。如果你希望进一步深入了解插件机制与审计设计推荐继续阅读仓库内的 插件手册、配置说明、新审计编写指南 以及 整体架构。【免费下载链接】lighthouseAutomated auditing, performance metrics, and best practices for the web.项目地址: https://gitcode.com/GitHub_Trending/lig/lighthouse创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表