ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Gatsby 插件性能基准测试实战:以 gatsby-plugin-manifest 的 onPostBootstrap 为例

Gatsby 插件性能基准测试实战:以 gatsby-plugin-manifest 的 onPostBootstrap 为例 Gatsby 插件性能基准测试实战以 gatsby-plugin-manifest 的 onPostBootstrap 为例【免费下载链接】gatsbyReact-based framework with performance, scalability, and security built in.项目地址: https://gitcode.com/gh_mirrors/ga/gatsby导读本篇文章以 Gatsby 仓库中的 benchmarks/plugin-manifest/README.md 为骨架完整还原如何对gatsby-plugin-manifest插件的构建期性能进行基准测试从一行yarn bench跑完整套流程到使用gatsby-dev把当前分支代码注入基准项目、精细测量onPostBootstrap生命周期钩子的执行耗时。读完本文你将掌握 Gatsby 官方基准测试项目benchmarks的目录结构与运行方式、插件性能测量的核心脚本设计以及gatsby-plugin-manifest在构建期生成 PWA manifest 与多尺寸图标的底层实现原理。一、为什么要给 Gatsby 插件做性能基准测试Gatsby 是构建时build time执行的 React 框架插件在构建期承担了大量工作。以gatsby-plugin-manifest为例它的核心工作——读取源图标、用 sharp 生成 8 个以上不同尺寸的 PNG、再写出manifest.webmanifest——全部发生在构建流程中。这类工作如果出现性能回退会直接拖慢所有使用该插件的站点构建。因此 Gatsby 仓库维护了一套 benchmarks 目录里面放置了针对不同场景create-pages、md、query、image-processing、各 CMS source 插件等的微型测试站点。其中 plugin-manifest 是专门针对gatsby-plugin-manifest构建期耗时的基准项目。该基准项目的定位非常纯粹反复执行插件最耗时的生命周期钩子onPostBootstrap统计单次耗时与平均耗时用数据量化插件性能并支持将当前开发分支的代码注入基准环境进行对比详见 benchmarks/plugin-manifest/README.md。二、快速开始Setup 与 Run原文档给出的启动方式极简只有两条命令# 在 benchmarks/plugin-manifest 目录下 yarn yarn benchyarn安装依赖。基准项目的依赖集中在 benchmarks/plugin-manifest/package.json运行时依赖只有fs-extra与gatsby-plugin-manifest开发依赖是gatsby-plugin-benchmark-reporting该插件用于向 Gatsby 的持续基准测试平台上报结果。yarn bench执行node index.js即直接运行 benchmarks/plugin-manifest/index.js 这个独立脚本而非触发一次完整的gatsby build。文档特别强调了一句话Benchmarks the current production version of the plugin unless you usegatsby-dev.即默认情况下基准测试测量的是当前已安装到node_modules的生产版本插件。只有当你使用gatsby-dev把源码编译产物注入本地node_modules时测的才是你正在编辑的分支代码。此外 benchmarks/plugin-manifest/package.json 还保留了常规站点脚本供对照使用scripts: { bench: set -x; node index.js, build: gatsby build, develop: gatsby develop, serve: gatsby serve }其中bench加了set -xshell 下回显实际执行命令方便确认脚本真实执行内容build/develop/serve则是标准 Gatsby 命令可用于对照一次完整构建的耗时。三、基准测试当前分支watch gatsby-dev 双进程协作原文档的核心操作章节讲解了两条命令的配合。要测量自己正在修改的分支上的插件性能需要两个终端进程第一步在仓库根目录启动 watch 编译# In the root of the Gatsby repository yarn run watch --scopegatsby-plugin-manifest .这条命令利用 monorepo 的 lerna/yarn workspaces 机制只监听gatsby-plugin-manifest这个包把它的 TypeScript/ES 源码实时编译到该包目录。之后你git checkout切换分支、修改代码改动都会被增量编译出来。第二步在基准目录用 gatsby-dev 注入本地包# In ./benchmarks/plugin-manifest # Youll need gatsby-dev installed and configured globally. gatsby-dev --packages gatsby-plugin-manifestgatsby-dev是 Gatsby 仓库自带的本地开发同步工具源码见 packages/gatsby-dev-cli。它会把本地packages/gatsby-plugin-manifest的最新编译产物复制/软链到当前站点目录的node_modules/gatsby-plugin-manifest从而让基准项目不再使用 registry 上发布的版本而是使用你本地的开发版本。之后你就可以放心地在分支之间切换git checkout、随意修改插件源码——每次改动经 watch 编译、再被gatsby-dev同步后基准测试跑到的就是最新代码。这正是原文档所说的You may now switch branches usinggit checkoutand edit code on the current branch. Changes will be compiled into the localnode_modulesfor the benchmark.这一watch 编译 gatsby-dev 注入的组合是 Gatsby 仓库所有 benchmark 项目通用的迭代测量方式也是做插件性能回归排查时的标准工作流。四、基准脚本剖析index.js 如何测量插件耗时真正执行测量的是 benchmarks/plugin-manifest/index.js它没有启动完整的 Gatsby而是直接调用插件的生命周期函数这使测量精度与可重复性都远高于整站构建计时。4.1 直接调用 onPostBootstrap脚本核心就一行const { onPostBootstrap } require(gatsby-plugin-manifest/gatsby-node) ... await onPostBootstrap({ reporter }, pluginOptions)它从gatsby-plugin-manifest/gatsby-node直接引入onPostBootstrap导出见 packages/gatsby-plugin-manifest/src/gatsby-node.js 中的exports.onPostBootstrap然后模拟 Gatsby 传入的 API 参数对象{ reporter }和插件配置对象。传给onPostBootstrap的测试配置如下即 benchmarks/plugin-manifest/index.js 中的pluginOptionsconst pluginOptions { name: GatsbyJS, short_name: GatsbyJS, start_url: /, background_color: #ffffff, theme_color: #663399, display: minimal-ui, icon: ../../www/src/assets/gatsby-icon.png, cache_busting_mode: none, }这组配置覆盖了插件最典型的用法基础 manifest 字段 源图标自动生成 关闭 cache bustingcache_busting_mode: none意味着不修改文件名的前提下全量生成图标这是最能反映图标生成原始成本的配置。需要说明icon指向仓库中www站点的图标资源相对基准目录为../../www/src/assets/gatsby-icon.png。由于本镜像仓库不包含www站点源码若要实际运行该基准需要自行准备一个存在的方形 PNG/SVG 图标并修改此路径——插件源码中doesIconExist见 packages/gatsby-plugin-manifest/src/node-helpers.js会校验图标文件是否存在不存在时makeManifest会直接抛错见 packages/gatsby-plugin-manifest/src/gatsby-node.js 中的错误提示。4.2 用 process.hrtime 计时每一轮测量使用 Node 的高精度计时器process.hrtime()const timeStart process.hrtime() await onPostBootstrap({ reporter }, pluginOptions) const timeEnd process.hrtime(timeStart)hrtime返回[seconds, nanoseconds]数组精度远超Date.now()适合毫秒级以下波动的性能采样。每轮结果被推入results.seconds与results.nanoseconds两个数组同时累加进sum。4.3 轮次控制与环境变量默认执行 20 轮可通过环境变量覆盖let rounds process.env.TOTAL_ROUNDS || 20即运行TOTAL_ROUNDS100 yarn bench可以加大采样量让平均/最大/最小耗时更稳定。4.4 每轮结束后的清理为了让每一轮都在干净状态下执行脚本在每轮计时结束后删除插件生成的产物fs.removeSync(public/icons) fs.removeSync(public/manifest.webmanifest)这正是为了规避插件内置缓存的影响onPostBootstrap内部使用checkCache见 packages/gatsby-plugin-manifest/src/gatsby-node.js以createContentDigest(${icon.src}${srcIcon}${srcIconDigest})为键判断图标是否已生成、避免重复生成。如果不清理public/icons后续轮次会命中缓存测出的就只是写 manifest 文件的耗时而非完整生成耗时。4.5 输出统计指标循环结束后脚本输出四类指标见 benchmarks/plugin-manifest/index.js 的runTestAveragesum / rounds即平均执行耗时MaxMath.max(...results.nanoseconds)最慢一轮MinMath.min(...results.nanoseconds)最快一轮RangeMax − Min波动幅度。这四个数字分别回答典型耗时、最坏情况、最佳情况、稳定性四个问题可用于对比不同分支/不同配置下的性能差异。4.6 基准站点的 gatsby-config 很薄benchmarks/plugin-manifest/gatsby-config.js 只有一个插件module.exports { plugins: [gatsby-plugin-benchmark-reporting], }基准项目本身不真正加载被测插件它由 index.js 直接调用gatsby-plugin-benchmark-reporting只是负责把本地测量结果上报给 Gatsby 官方的性能监控平台属于基准测试的基础设施与 index.js 的本地测量逻辑解耦。五、原理纵深onPostBootstrap 到底在做什么理解了脚本测量的是onPostBootstrap之后值得深入 packages/gatsby-plugin-manifest/src/gatsby-node.js 看看这一钩子的真实成本构成——这正是基准测试要量化的对象。onPostBootstrap的整体流程可以拆成几步对应源码exports.onPostBootstrap与makeManifest函数启动 activity 计时器调用reporter.activityTimer(Build manifest and related icons)并向 reporter 汇报进度——这也是为什么基准脚本需要传{ reporter }实际使用gatsby-cli/lib/reporter。合并默认图标集若配置未提供icons则注入defaultIcons——即 48、72、96、144、192、256、384、512 共 8 个尺寸见 packages/gatsby-plugin-manifest/src/common.js 的exports.defaultIcons。校验并读取源图标doesIconExist检查文件存在性用 sharp 读取元数据若宽高不等会reporter.warn提示图标不是正方形。按 cache_busting_mode 生成图标processIconSet依据query/name/none三种模式决定在加 digest 之前还是之后生成addDigestToPath的实现见 packages/gatsby-plugin-manifest/src/common.js。generateIcon用 sharp 做resize({ width: size, height: size, fit: contain, background: 透明 })输出到public/icons/。生成 faviconinclude_favicon默认开启onPreInit中默认true对favicons数组32x32执行同一套生成流程若源图标是 SVG还会额外复制为public/favicon.svg。处理 basePath 与 start_url 前缀为多站点/路径前缀场景拼接basePath源码注释标记为 Fix #18497。写出 manifestfs.writeFileSync(path.join(public, manifest.webmanifest), JSON.stringify(manifest))。此外onPostBootstrap还支持localize数组当配置了多语言时会对每个 locale 并行执行一次makeManifest并为带独立icon的 locale 自动强制cache_busting_mode: name避免多语言间图标相互覆盖。成本分析单次onPostBootstrap的耗时主要来自第 4/5 步——8 个默认图标加 1 个 favicon 共 9 次 sharp 缩放编码写盘。基准脚本把cache_busting_mode设为none并清理产物就是为了把缓存因素剔除测量最纯粹的计算与 I/O 成本。六、测试与验证仓库内的佐证如果你想在仓库内直接验证插件行为而不跑完整基准可参考插件的单元测试packages/gatsby-plugin-manifest/src/tests/gatsby-node.js覆盖onPostBootstrap/makeManifest的核心行为包括本地化localize、cache_busting_mode各模式的图标路径与 digest 行为packages/gatsby-plugin-manifest/src/tests/common.js验证addDigestToPath在name/query模式下的路径拼接快照目录 packages/gatsby-plugin-manifest/src/tests/snapshots记录了生成的 manifest 与 SSR 输出。这些测试与基准脚本互为印证基准测的是耗时不回归单测保证的是行为不回归。七、运行注意事项与常见问题结合插件文档packages/gatsby-plugin-manifest/README.md与基准项目本身运行/扩展该基准时有几点值得注意源图标必须存在且尽量为正方形建议尺寸不小于最大生成尺寸512x512。若图标宽高不等插件会加透明边补成正方形并给出警告若文件不存在onPostBootstrap直接抛错基准脚本会失败。gatsby-dev需要全局安装与配置原文档明确说明 Youll need gatsby-dev installed and configured globally且gatsby-dev与仓库根目录的yarn run watch必须配合使用二者缺一不可。清理逻辑与缓存若修改 index.js 去掉fs.removeSync清理测得的将是命中缓存的耗时数值会显著偏小不能与默认结果直接对比。调整采样量通过TOTAL_ROUNDS环境变量加大轮次可降低单轮抖动对平均值的干扰。生产版本 vs 开发版本不做gatsby-dev注入时测的是node_modules中已发布版本要对比发布版 vs 当前分支可先后各跑一次yarn bench记录四类指标再对比。sharp 版本冲突若基准环境安装依赖时报Incompatible library version: sharp.node requires version X...说明项目里存在多个不兼容的 sharp 副本可执行npm list sharp/yarn why sharp定位并统一版本官方建议同步升级gatsby-plugin-sharp、gatsby-plugin-manifest、gatsby-transformer-sharp等相关包。Apache 环境注意/icons目录限制自动模式生成的图标默认放在public/icons/Apache 默认禁止访问/icons路径可通过 hybrid 模式把输出目录改为favicons等自定义名规避详见 packages/gatsby-plugin-manifest/README.md 的 Troubleshooting 章节。八、小结如何把该基准用于插件性能回归把 benchmarks/plugin-manifest/README.md 的完整方法论浓缩成一张操作清单在仓库根目录yarn run watch --scopegatsby-plugin-manifest .启动增量编译在 benchmarks/plugin-manifest 目录安装依赖yarn并运行gatsby-dev --packages gatsby-plugin-manifest注入本地代码执行yarn bench可加TOTAL_ROUNDS提高采样得到 Average / Max / Min / Range 四组耗时用git checkout切换分支、修改源码重复第 3 步对比数据结合 index.js 的清理逻辑与插件源码中的缓存/生成流程解释耗时差异的根因。这套直接调用生命周期钩子 高精度计时 产物清理 多轮统计的测量模式不只是gatsby-plugin-manifest专属它代表了 Gatsby benchmarks 目录下所有微基准项目的通用设计哲学脱离完整构建管线精准隔离单个插件的构建期成本。理解了它你就能用同样的思路为任何自定义 Gatsby 插件搭建轻量性能回归基准。【免费下载链接】gatsbyReact-based framework with performance, scalability, and security built in.项目地址: https://gitcode.com/gh_mirrors/ga/gatsby创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表