Gatsby v3.10 深入解析:Parallel Query Running 与 webpack 持久缓存两大实验特性
2026/9/20 9:21:52 网站建设 项目流程
  • 前端
  • 静态站点
  • Web框架

【免费下载链接】gatsby

React-based framework with performance, scalability, and security built in.

项目地址:https://gitcode.com/gh_mirrors/ga/gatsby
点击查看免费下载

Gatsby v3.10.0(2021 年 7 月第二个版本)的核心主题是为构建链路中最耗时的环节注入并行能力与缓存能力:一方面通过PARALLEL_QUERY_RUNNING实验特性把原先只能在单进程内串行执行的查询运行(query running)分散到多个子进程中,充分利用多核 CPU 与内存;另一方面通过DEV_WEBPACK_CACHE实验特性把 webpack 5 的文件系统持久缓存引入gatsby develop,显著缩短开发服务器启动时间。读完本文,你将掌握这两个实验特性的开启方式、底层实现原理(gatsby-worker+ LMDB)、官方基准测试方法,以及它们在后续 Gatsby 版本中的演进去向。

一、发布背景:v3.10 的两个关键词

Gatsby 的构建过程由多个步骤串联而成(详见 Gatsby 构建流程概览),其中有一个步骤会随着页面(pages)和数据节点(nodes)数量的增长而不断变慢,这就是查询运行。在构建日志中,你通常能看到两个进度条目:

  • run static queries(静态查询)
  • run page queries(页面查询)

v3.10 之前的查询运行步骤只在单一进程中执行,无法利用现代服务器普遍具备的多核 CPU 与富余内存。v3.10 推出的实验特性 Parallel Query Running(PQR,并行查询运行)目标就是把查询工作分发到多个进程中,从而更好地利用可用核心与内存。

与此同时,Gatsby 在 v3.8 中已经为生产构建(production build)启用了 webpack 5 的持久缓存(见 v3.8 发布说明),v3.10 则开始把同样的能力逐步推广到gatsby develop,以大幅缩短开发服务器启动时间。

Bleeding Edge 提示:如果你希望第一时间体验新特性,可以安装gatsby@next版本,并在遇到问题时向官方提交 issue。上一版本见 v3.9 发布说明。

二、实验特性一:Parallel Query Running(PARALLEL_QUERY_RUNNING

2.1 为什么查询运行是构建瓶颈

在 Gatsby 的构建过程中,查询运行阶段需要为每一个页面执行 GraphQL 查询,并写入对应的page-data.json。页面越多、节点越多,这一步耗时越长。由于它此前只能在单进程内顺序执行,即便机器有 16 核,查询工作也只会吃掉一个核的算力。这正是 PQR 想要解决的痛点。

2.2 底层实现:gatsby-worker+ LMDB

PQR 的实现依赖两个关键基础设施:

  1. gatsby-worker:Gatsby 自研的子进程任务调度工具,其设计高度借鉴了社区广受欢迎的jest-worker。仓库中 gatsby-worker 源码 清楚地展示了它的工作方式:
    • 基于 Node.jschild_processfork方法派生子进程,每个 worker 进程通过 IPC 与主进程通信;
    • 提供WorkerPool类,将 worker 模块中导出的函数自动暴露为single(调度到某一个 worker 执行,用于任务分发)和all(在所有 worker 上执行,用于初始化等场景)两类方法;
    • 内置TaskQueue任务队列,空闲 worker 会自动从队列中领取下一个任务(见 index.ts 中的checkForWork逻辑);
    • 每个 worker 会继承主进程环境变量,并获得额外的GATSBY_WORKER_ID标识;numWorkers默认值为 1,未指定时只派生一个 worker(见 gatsby-worker README)。
  2. LMDB(lmdb-store:Gatsby 在 v3.7 引入了 LMDB 实验性数据存储(见 v3.7 发布说明),将节点数据从纯内存(Redux)改为持久化、可嵌入的存储,以降低大型站点的峰值内存占用。PQR 正是复用了这套 LMDB 数据存储,让主进程与 worker 进程之间可以高效共享数据——worker 不需要把整棵节点树拷贝进自己的内存,而是直接读取持久化存储中的节点。

从构建流程的代码组织也能看到查询运行所处的位置:构建命令在 build.ts 中依次调用runStaticQueriesrunPageQueries两个服务(对应 services/index.ts 的导出),其中页面查询服务在 run-page-queries.ts 中实现,其进度活动名称正是日志里看到的run page queries。PQR 开启后,这一阶段的任务会被改派给 worker 进程池执行(日志显示为run queries in workers)。

2.3 官方基准测试:性能提升幅度取决于查询类型

v3.10 发布说明给出了两组实测示例数据,它们来自官方仓库中的 query-filters-sort 基准测试(通过切换特性开关做前后对比,使用GATSBY_CPU_COUNT=5限制为 5 个 worker):

查询类型配置开启前(单进程)开启后(worker)
快速的eq-uniq过滤器GATSBY_CPU_COUNT=5 NUM_NODES=100000 NUM_PAGES=10000 FILTER=eq-uniq TEXT=1run page queries - 3.787s - 10001/10001 2641.07/srun queries in workers - 3.445s - 10001/10001 2903.34/s
较慢的gt过滤器GATSBY_CPU_COUNT=5 NUM_NODES=10000 NUM_PAGES=10000 FILTER=gt TEXT=1run page queries - 41.832s - 10001/10001 239.07/srun queries in workers - 15.072s - 10001/10001 663.57/s

结论要点(以上为 2021 年 7 月官方发布说明中的实测示例,具体提升幅度会随站点类型与运行环境变化):

  • 对于本身已经很快的eq类"快速过滤器"(Fast Filters),并行化带来的提升相对有限(如eq-uniq从约 3.8s 降到约 3.4s);
  • 对于gt这类复杂过滤条件、无法走快速路径的查询,提升非常显著(从约 41.8s 降到约 15.1s,吞吐从 239/s 提升到 663/s)。

也就是说:站点使用的查询类型决定了你能获得多大的收益,复杂查询越多,收益越大。

2.4 如何在自己的站点中开启

官方给出的启用步骤分两步:

第一步:确认 Node 版本并安装lmdb-store依赖

PQR 依赖 LMDB 持久化存储,官方要求使用Node v14.10 或更高版本

npm install lmdb-store

第二步:在gatsby-config.js中开启特性标志

module.exports = { flags: { PARALLEL_QUERY_RUNNING: true, }, }

2.5 使用官方基准测试复现对比

如果你想在自己的环境里量化 PQR 的收益,可以使用仓库自带的 query-filters-sort 基准测试。该基准会创建指定数量的数据节点并生成指定数量的页面,对多种过滤器(eqeq-uniqingtltninneregex等)进行压力测试,并支持可选的排序(SORT)与计数(COUNT)维度。核心环境变量如下:

  • NUM_NODES:创建的数据节点数量(默认 1000)
  • NUM_PAGES:生成的页面数量(默认 1000,必须 ≤NUM_NODES
  • FILTER:过滤器类型,例如eq(默认,命中 1/4 节点)、eq-uniq(按唯一值命中单节点)、gt(范围过滤)、regex(正则过滤)等
  • SORT:是否排序,0为不排序(默认),1按随机数排序,也可传逗号分隔的字段列表
  • TEXT1时为每个节点附加 4KB 随机文本(会增大page-data.json
  • COUNT1时在查询中请求totalCount

例如,想要研究gt过滤器的时间复杂度,可以保持页面数不变、逐步增加节点数运行三次:

NUM_NODES=1000 FILTER=gt yarn bench NUM_NODES=10000 FILTER=gt yarn bench NUM_NODES=100000 FILTER=gt yarn bench

gatsby-config.js中切换PARALLEL_QUERY_RUNNING标志即可得到开/关两套日志,用于前后对比。

2.6 已知问题与反馈渠道

官方提示该特性存在一些已知的常见陷阱与解决方案,相关讨论与反馈集中在 PQR 专项讨论帖中;此外,由于 LMDB 依赖原生模块,在 WSL1 环境下运行会遇到类似Error: MDB_BAD_RSLOT: Invalid reuse of reader locktable slot的报错(上游 WSL 问题,见 从 v3 迁移到 v4 的说明),官方建议升级到 WSL2。

三、实验特性二:webpack 持久缓存加速gatsby developDEV_WEBPACK_CACHE

3.1 背景:生产构建已启用,开发模式跟进

Gatsby 在 v3.8 中为生产构建引入了 webpack 5 持久缓存(见 v3.8 发布说明),v3.10 开始将其逐步推广到gatsby develop。持久缓存让 webpack 的编译中间结果落盘复用,从而大幅改善开发服务器的启动时间——第二次及后续启动时无需重新编译全部模块。

3.2 源码层面的缓存配置

在 webpack.config.js 中可以找到这一缓存能力的实现:当构建阶段为build-javascriptbuild-htmldevelopdevelop-html时,Gatsby 会为 webpack 配置文件系统缓存(type: "filesystem"),缓存位置为站点根目录下.cache/webpack/stage-<阶段名>,并将__filename(webpack 配置本身)与所有实现了onCreateWebpackConfigAPI 的插件路径作为buildDependencies——这意味着当 webpack 配置或相关插件变化时,缓存会自动失效重建。从源码结构可以推断,DEV_WEBPACK_CACHE标志的作用正是让developdevelop-html阶段启用这套持久缓存。

3.3 如何开启

gatsby-config.js中添加标志即可:

module.exports = { flags: { DEV_WEBPACK_CACHE: true, }, }

3.4 与FAST_DEV的关系

如果你已经在使用FAST_DEV标志,那么升级到 Gatsby v3.10 后会自动获得该缓存能力,无需额外配置。从 flags.ts 可以看到,FAST_DEV是一个面向develop命令的"总开关",它通过includedFlags自动附带开启DEV_SSRPRESERVE_FILE_DOWNLOAD_CACHE等实验,目标是整体改善开发服务器启动时间与开发体验。使用过程中的缓存清理相关问题可在专门的反馈讨论中提交。

四、值得关注的 Bugfix 与改进

除两大实验特性外,v3.10 还包含一系列质量改进(以下为发布说明中列出的官方条目):

  • gatsby:升级postcss到 8.3.5,消除 Node v16 下的弃用警告。
  • gatsby:将createRoot切换为hydrateRoot(仅在你使用 React 18 时生效)。从当前仓库代码可以印证这一演进:在 cache-dir/app.js 中,Gatsby 会根据是否支持 React 18 分别调用reactDomClient.hydrateRootreactDomClient.createRoot;cache-dir/react-dom-utils.js 中同样实现了这两套渲染路径的分支处理。
  • gatsby-source-wordpress:更早地校验预览 URL,并给出更友好的错误反馈(PR #32251)。
  • gatsby:在重定向的最终 URL 以及 Service Worker 更新之后,正确传递window.locationsearchhash参数(PR #32334、PR #32323)。
  • gatsby:修复按Ctrl + C退出时出现的UNHANDLED REJECTION write EPIPE错误(PR #32311、PR #32356)。
  • gatsby:当gatsby build因数据缺失等原因失败时,现在会打印对应页面的page-data.json文件内容,以提供更多上下文帮助定位问题(PR #32301)。
  • gatsby-source-contentful:支持从 Image API 读取图片圆角(corner radius)参数(PR #32333)。
  • gatsby-source-contentful:支持metadata.tags属性(PR #31746)。

五、这两个实验特性的后续演进

从仓库中的迁移文档可以清楚看到这两个实验特性的最终去向:

  • DEV_WEBPACK_CACHE进入核心:在 从 v3 迁移到 v4 的说明 中明确写道,DEV_WEBPACK_CACHEQUERY_ON_DEMANDLAZY_IMAGESFUNCTIONSPRESERVE_WEBPACK_CACHE这些标志已并入 Gatsby 核心,不再需要通过gatsby-config.js显式开启(也无法再关闭)。
  • PARALLEL_QUERY_RUNNINGDEV_WEBPACK_CACHE标志被移除:在 从 v4 迁移到 v5 的说明 中,两者均被列入已删除的实验标志清单——并行查询运行成为 Gatsby v4/v5 的默认构建行为。
  • Node 版本要求:v4 起 Gatsby 放弃对 Node 12 的支持,因为底层新依赖lmdb-store要求 Node>=14.15.0(见 从 v3 迁移到 v4 的说明);v4 之后 Gatsby 也统一使用 LMDB 作为节点数据的持久化存储。

也就是说,如果你现在使用的是 Gatsby v4 或更高版本,这两项能力已经内建并默认生效,无需再配置本文中的实验标志;而如果你仍在使用 v3.x,则可以按照上面的步骤体验这两个实验特性。

六、社区贡献者致谢

v3.10 收到了多位社区贡献者的参与,包括:修复示例中作者名过滤器错误 ID(RapTho)、更新 Storybook 指南至 v6(anselm94)、修复创建源插件教程中缺失的括号(SarthakC)、替换 Google Analytics 域名为 Google Tag Manager(emmanuelgautier)、在swUpdated后传递search/hash到 location(nellaparedes)、修复 Ctrl+C 下的未处理拒绝错误(karlhorky)、更新文档说明翻译暂停状态(weronikadominiak)、修正 apollo/client 包名拼写(cabutler10)、更新 building-a-theme 至最新 Theme UI(ezeYaniv)、修正 JavaScript 拼写(SonnyBrooks),以及为gatsby-source-contentful增加图片圆角与 tags 支持的 axe312ger 等。


相关资源速查

  • v3.10 发布说明原文
  • Gatsby 构建流程概览
  • v3.9 / v3.8 / v3.7 发布说明(同目录下可找到 v3.8、v3.7 等历史版本)
  • gatsby-worker 源码与 API 文档
  • query-filters-sort 基准测试
  • webpack 缓存配置实现
  • 从 v3 迁移到 v4 / 从 v4 迁移到 v5
  • 前端
  • 静态站点
  • Web框架

【免费下载链接】gatsby

React-based framework with performance, scalability, and security built in.

项目地址:https://gitcode.com/gh_mirrors/ga/gatsby
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询