gatsby-source-wordpress 插件架构深度解析:从 WPGraphQL 远程 Schema 摄取到节点获取的完整数据管线
2026/9/21 2:33:56 网站建设 项目流程
  • 前端
  • 静态站点
  • Web框架

【免费下载链接】gatsby

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

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

导读

gatsby-source-wordpress^4.0.0)是 Gatsby 官方基于WPGraphQL的 WordPress 数据源插件,它不再像 v3 那样调用 WordPress REST API,而是通过 GraphQL introspection 远程摄取 WPGraphQL Schema、自动生成查询、定制 Gatsby Schema、并以游标分页方式抓取节点与媒体文件。本文以仓库中 ARCHITECTURE.md 为骨架,结合插件源码(位于 packages/gatsby-source-wordpress/src)逐层拆解其数据管线、缓存策略、Preview 机制与开发体验设计,读完你将理解这个 Gatsby 生态中体量最大的源插件之一是如何组织代码、处理增量更新与应对大型站点抓取可靠性问题的。

历史背景:从 REST API 到 WPGraphQL 的重写

gatsby-source-wordpress@^3.0.0使用 WordPress REST API 获取数据,而^4.0.0改用WPGraphQL,两者是完全没有共享代码的"两个插件"。v4 的早期工作最初在独立的 [gatsby-source-wordpress-experimental] 仓库中进行,之后才合并进 Gatsby monorepo。

这个插件还催生了 [Gatsby GraphQL Toolkit]——一个用于创建 GraphQL API 源插件的工具库。不过由于插件诞生时 toolkit 尚不存在,且插件具备 toolkit 目前不具备的特性,因此插件并未迁移到 toolkit 上,作者在文档中坦言"迁移收益小、成本可能高达数月"。

另一个值得注意的历史决策是语言选择:插件最初用 JS 编写,后部分移植到 TS,因此源码中 JS/TS 文件混杂。当时 Gatsby 核心团队约定核心用 TS、插件用 JS 以降低社区贡献门槛,但这个插件最终成为 Gatsby 插件中最大的代码库之一,作者后来认为它"100% 需要 TS"。从仓库看,src/steps下确实是.js.ts并存的状态(例如 src/steps/source-nodes/index.ts 是 TS,而 src/steps/source-nodes/fetch-nodes/fetch-nodes.js 是 JS)。

入口与步骤组织:gatsby-node.tssrc/steps

插件 99.999% 的逻辑都从gatsby-node.ts进入(gatsby-browser.ts只导入 1 个 CSS 文件)。仓库根目录的 gatsby-node.js 只是一个转发表层:module.exports = require("./dist/gatsby-node"),真正的实现编译到dist目录。

所有业务"步骤"(step)各自独立成文件,统一放在src/steps目录,并通过 src/steps/index.ts 统一导出。从中可以看到插件挂载的 Gatsby Node API 全貌:

  • setGatsbyApiToState/ensurePluginRequirementsAreMet/ingestRemoteSchema/createSchemaCustomization/sourceNodes/setErrorMap等主流程步骤;
  • startPollingForContentUpdates(开发模式内容轮询,见 content-update-interval.js);
  • checkIfSchemaHasChanged(远程 Schema MD5 对比,见 diff-schemas.js);
  • Preview 相关:onCreatePageRespondToPreviewStatusQueryonCreatepageSavePreviewNodeIdToPageDependencyonPreExtractQueriesInvokeLeftoverPreviewCallbacks
  • pluginOptionsSchema(Joi 定义的插件选项校验与文档生成);
  • setRequestHeadersaddRemoteFileAllowedUrlimageRouteshideAuthPluginOptions/restoreAuthPluginOptions(Basic Auth 相关)等辅助步骤。

步骤编排机制:多个步骤通过runSteps顺序执行。以远程 Schema 摄取为例,src/steps/ingest-remote-schema/index.js 展示了完整的流水线:

checkIfSchemaHasChanged → introspectAndStoreRemoteSchema → identifyAndStoreIngestableFieldsAndTypes → [buildNodeQueries, buildNonNodeQueries] → [cacheFetchedTypes, writeQueriesToDisk]

其中buildNodeQueriesbuildNonNodeQueries并行、cacheFetchedTypeswriteQueriesToDisk并行,说明查询构建阶段允许分支并发。

查询生成 / 远程 Schema 摄取

在从 WPGraphQL 抓取任何数据之前,插件必须先知道"该问 WPGraphQL 要什么"。做法是:

  1. 向 WPGraphQL 发起一次introspection 查询(见introspect-remote-schema.js),拿到远程 Schema 的完整描述;
  2. 使用自定义查询构建器(build-queries-from-introspection,位于 src/steps/ingest-remote-schema)根据 introspection 响应生成节点列表查询;
  3. 这些查询存储在本地,供后续sourceNodes阶段使用。

这段逻辑在 Gatsby Node APIcreateSchemaCustomization阶段运行(与 Schema 定制共用同一次 introspection 结果)。

查询生成的几个工程细节(Good to know)

文档明确列出了设计上的权衡,这些在代码结构上也能印证:

  • 只抓缺失数据:因为插件知道哪些会变成未来的 Gatsby 节点,节点之间的连接(connection)只抓取id,避免冗余;
  • 自动 fragment 化:当某个带 selection set 的字段被查询超过 1 次时,自动生成 fragment 以控制查询体积;
  • 双向连接造成过度抓取:目前User.posts[].idPost.author.id两侧都会抓取,作者认为未来应允许某些字段完全由 Gatsby 侧解析(既然有了Post.author.id,就无需User.posts[].id);
  • "全量抓取"是开发模式的必要代价:插件不知道站点最终会用到哪些字段,因此抓取全部可用的 WPGraphQL 数据;gatsby develop下这是必须的,但理论上冷构建和gatsby build的非开发更新可以只抓被查询的字段;
  • 查询复杂度拆分是未来方向:目前内部已支持存储多个查询,未来应加入查询复杂度算法(或复用 WPGraphQL 的),把过大查询自动拆分为多个。

Schema 定制

查询生成与 Schema 定制共享同一次 introspection 结果。在createSchemaCustomization阶段,插件把远程 Schema 转换为符合 Gatsby 节点模型、并受插件选项约束的 WP/Gatsby Schema。核心代码在 src/steps/create-schema-customization,其中:

  • index.js 遍历introspectionData.__schema.types,根据type.kindUNION/INTERFACE/OBJECT/ENUM/SCALAR)调用对应的类型构建器;
  • transform-fields 目录下的字段转换器(field transformer)把远程 introspection 字段转为 Gatsby Schema 定制层能理解的 type/field 定义;
  • 所有 resolver 都在 Gatsby 侧完成——这是对 WPGraphQL 中 resolver 行为的"自动复刻",且仅针对没有输入参数(input args)的字段。文档明确指出:目前没有(大概率永远不会有)自动搬运 WPGraphQL 输入参数的机制,因此带输入参数的字段会被跳过(在非节点 root fields 的处理中也能看到同样策略)。

Schema 定制与查询生成的交互

同时影响这两块逻辑的插件选项集中在插件选项文档的schema一节(见 docs/plugin-options.md 的schema部分),典型如schema.perPageschema.requestConcurrencyschema.timeoutschema.typePrefix

已抓取类型即可查询类型(Fetched Types are Queryable Types)

查询生成过程中会记录"哪些类型和字段被查询过",这份清单随后被用于 Schema 定制:任何因插件选项或内部逻辑而未抓取的字段/类型,都会从 Gatsby Schema 中被省略。这保证了 Schema 与抓取数据严格一致,也解释了为什么两个阶段必须共享同一份 introspection 结果(源码中cacheFetchedTypes步骤正是把已抓取类型写入缓存的实现)。

自动字段前缀(Automatic Field Prefixing)

当 Union 或 Interface 类型的多个成员包含同名字段时,查询生成阶段会把这些字段自动加前缀为Typename.fieldName;Schema 定制阶段则配套实现 resolver 逻辑来应对这种重命名。文档强调:[Typename].[fieldName]必须总能解析到单一类型(把 union/interface 视为单一类型考虑),否则大量接口/联合类型会因字段冲突而不可查询。

Schema 缓存:MD5 差异比对

远程 Schema 摄取自带缓存机制,见 src/steps/ingest-remote-schema/diff-schemas.js。其核心思路:

  1. 通过一次 GraphQL 请求同时拿到schemaMd5与 WordPressgeneralSettings.url(顺带省一次请求);
  2. 把当前远程 Schema 的 MD5 与缓存中上次的 MD5 对比;
  3. 若 MD5 不同(schemaWasChanged),全部重新生成查询,并重新执行 Schema 定制
  4. 生产环境下这会触发插件重新抓取所有节点(因为无法确定新 Schema 是否包含新增或变更的数据);开发环境下只更新 Schema 并打印警告——如果 Schema 更新涉及数据变化,提示开发者运行gatsby clean

文档给出一组关键性能数字:没有这个机制时,"每次生产数据更新会慢 10–30 秒",而开发环境下 Schema 变更若导致全量重抓,"每次修改 WPGraphQL Schema 都要等 5 分钟以上"。diff 逻辑还顺带做了几件防御性工作:校验pluginOptions.url与 WP 设置中 URL 的协议是否一致(不一致会警告,见 diff-schemas.js)、在 Schema 变更时重新检查远程插件版本要求、以及处理硬缓存失效。

值得注意的细节:当缓存中已有 MD5 且本次是刷新(非initial-createSchemaCustomization)时,Schema 变化会触发ensurePluginRequirementsAreMet重新校验 WPGraphQL/WPGatsby 版本兼容性(见 diff-schemas.js)。

节点获取(Sourcing Nodes)

节点抓取使用前面生成的查询,通过游标分页(cursor pagination)从 WPGraphQL 拉取,核心实现在 src/steps/source-nodes/fetch-nodes/fetch-nodes.js:fetchWPGQLContentNodes调用paginatedWpNodeFetch,以schema.perPage为每页大小循环分页,最终汇总allNodesOfContentType

影响抓取行为的插件选项

文档明确指出以下选项直接影响节点抓取逻辑(对应 src/steps/declare-plugin-options-schema.js 中schema一节的 Joi 定义):

选项默认值说明
type.<Type>.limit视类型而定限制某类型抓取的节点数量
schema.requestConcurrency15节点抓取期间的并发 GraphQL 请求数,WP 服务器崩溃时可调低
schema.perPage100节点抓取时每页抓取的节点数

没有内置重试的游标分页,及其原因

插件当前没有为节点抓取内置请求重试逻辑,这是有意为之的设计取舍:游标分页是一条很长的请求链,链上任何一次请求失败都会阻断后续所有请求。这带来两个限制:

  • 单个节点类型内的请求并发被压到 1(同一时刻只能有一个分页请求在途);
  • 无法"先把更耗资源的查询放到后面再重试,同时继续处理其他查询"。

文档给出的未来方向是:让 WPGatsby 支持一次返回最多 1 万个节点 id 的列表(这些请求仍是游标分页),拿到全部 id 后再构造"按 id 批量取节点"的查询,从而提升请求并发并干净地重试失败请求(如把单次请求的节点列表拆成两份以降低单次资源消耗)。

被引用的 MediaItem:按需抓取 + 队列尾部重试

节点抓取过程中,每个节点都会用正则分析出指向MediaItem(即 WPGraphQL 的 File 节点)的连接 id,见 src/steps/source-nodes/fetch-nodes/fetch-referenced-media-items.js。当其他所有节点类型抓取完成后,插件拿着这些 id批量抓取 MediaItem——好处是只抓站点真正用到的文件(很多 WP 管理员上传的文件数是实际用量的 5–10 倍)。

由于预先掌握了全部 id,这批请求不需要游标分页,从而可以运行"更精巧的重试逻辑":把失败请求追加到请求队列末尾重试,而不是原地重试。作者在文档中记录了自己的实验结论:把 MediaItem 请求放到队列尾部重试(而非立即原地重试),在 2 万+ 节点的大型站点上显著提升了抓取可靠性,同时因为并发可以拉高,小站点抓取也明显变快。源码中可以看到实现细节:mediaFileFetchQueue使用PQueue,文件下载并发默认受环境变量GATSBY_CONCURRENT_DOWNLOAD(默认 200)控制并预留 2 个给节点抓取;重试超过 1 次会按timesRetried * 500毫秒暂停,且最多重试 2 次(见 fetch-referenced-media-items.js)。

兼容性 API:面向 DX 与安全的设计

插件依赖 WordPress 侧安装并启用WPGatsbyWPGraphQL两个 PHP 插件,且必须版本匹配。由于无法假定远端站点将来会保持正确版本,插件引入了"远程兼容性 API":

  • 版本范围定义在 src/supported-remote-plugin-versions.ts,当前源码中的支持范围是WPGraphQL >=1.1.2 <3.0.0WPGatsby >=0.9.0 <3.0.0
  • 校验逻辑areRemotePluginVersionsSatisfied在 src/steps/check-plugin-requirements.ts 中实现:插件把版本范围(而非精确版本)发给 WPGatsby 暴露的wpGatsbyCompatibilityGraphQL 字段,由远端判断自己的 WPGraphQL/WPGatsby 版本是否落在范围内。

为什么只发版本范围而不是直接暴露版本号?文档给出安全考量:黑客可以扫描互联网上安装了"存在漏洞版本"插件的站点。如果只发送版本范围(不含具体补丁版本号),黑客无法确定某个有漏洞的版本是否已被修补,从而更难精准定位存在漏洞的站点。这是把 DX 校验与安全设计结合的典型例子。

状态管理:Rematch(Redux 封装)

插件使用Rematch(一个 Redux 封装库)管理全局状态,models 定义在 src/models/index.ts(同目录下还有gatsby-api.tsremoteSchema.tsdevelop.tspreview.tslogger.ts等 model 文件)。文档直言:如果重新设计会选择状态机库,且当前使用的是 Rematch 较老版本(新版本 API 变动较大,没有升级动力)。

Gatsby Node API helpers 存放在本地 Redux 而非 Gatsby Redux

每个 Node API 开始时setGatsbyApiToState(见 src/steps/set-gatsby-api-to-state.ts)会把 Gatsby Node API helpers(如actionscachereporterstore等)存入插件的 Rematch model。这样深层嵌套的函数无需层层传参就能使用 Gatsby 的 actions 与 helpers。比如 src/steps/source-nodes/index.ts 中就是通过getStore().getState().gatsbyApi取出helperspluginOptions

缓存体系:三个组成部分

插件缓存由三部分组成(对应 docs/features/caching.md 的详细说明):

1. 远程 Schema 变化(MD5 差异比对)

即上文所述的 diff-schemas.js:生产环境 MD5 变化则全量重抓,开发环境只更新 Schema 并警告运行gatsby clean

2. ActionMonitor(WPGatsby 变更事件)

这是增量更新的核心机制:

  1. 冷构建完成后,把当前时间戳存入缓存(LAST_COMPLETED_SOURCE_TIME,见 src/constants);
  2. 后续每次构建,插件通过 GraphQL 查询把该时间戳发给 WPGraphQL/WPGatsby/WordPress,询问"自上次抓取以来发生了什么变化";
  3. 插件拉取一串变更事件(actionMonitorActions),遍历并处理CREATE / UPDATE / DELETE事件(见 src/steps/source-nodes/update-nodes/wp-actions);
  4. 每次更新完成后写入新时间戳,供下次查询使用。

由于 WordPress 本身不存储这些事件,WPGatsby 里存在大量自定义逻辑,钩住 WordPress 的各种事件并把数据存入 WP 数据库(对应 WPGatsby 仓库src/ActionMonitor目录)。Gatsby 侧的增量入口是 fetch-node-updates.js,fetchAndApplyNodeUpdates({ since })调用fetchAndRunWpActions应用变更。

3. 硬缓存文件与数据(改善本地开发 DX)

Gatsby 会主动清空缓存(它不像源插件那样了解单个源的上下文),为此插件增加了"硬缓存"选项:把数据缓存在Gatsby 缓存之外,避免安装 NPM 包或修改gatsby-config.js/gatsby-node.js导致重新抓取成百上千张图片或节点。

相关选项定义在 src/steps/declare-plugin-options-schema.js 中(搜索hardCacheMediaFileshardCacheData可定位实现):

  • develop.hardCacheMediaFiles/production.hardCacheMediaFiles(默认false):媒体文件硬缓存到项目根目录的./.wordpress-cache/path/to/media/file.jpeg
  • develop.hardCacheData(默认false):WordPress 数据硬缓存到./.wordpress-cache/caches,当远程 WPGraphQL Schema 变化或插件选项变化时会自动清空自身。

实现上,src/utils/cache.tsCache类基于cache-manager+cache-manager-fs-hash,缓存目录为.wordpress-cache/caches。文档特别提醒:这两个选项是实验性 API,不保证数据有效性,主要目的是提升本地开发 DX;使用时应把.wordpress-cache目录加入.gitignore

Basic Auth

Basic Auth 选项服务于服务器级认证,而非 WP 级认证。设计原因是:Gatsby 数据应视为公开数据,任何非公开数据都不应暴露给 Gatsby,否则可能通过 GraphQL 查询或运行中 Preview 实例的/__graphql端点意外泄露。该选项的目的是允许你把 WPGraphQL 的/graphql端点锁起来,只允许带凭证的请求访问。详见 docs/features/security.md。

调试选项

插件提供了大量调试选项,用于打印处理过程中的各类信息,分散在代码库各处。全部调试选项集中收录在插件选项文档的debug一节(见 docs/plugin-options.md 中debug部分),例如debug.previewdebug.timeBuildStepsdebug.disableCompatibilityCheck等。另外pluginOptions.verbose控制是否输出更详细的日志(在 diff-schemas.js 等多处可见其开关作用)。

插件选项 Schema 与文档生成

插件选项 Schema 定义在 src/steps/declare-plugin-options-schema.js(该文件故意不用 TS,以便在 yarn 脚本中无需转译直接运行)。它基于 Gatsby 的Joi插件选项校验体系,每个选项都带有descriptionexample元数据。

自动化文档生成:每次yarn build时同时执行yarn generate-plugin-options-docs,该 npm 脚本运行仓库根目录的 generate-plugin-options-docs.js,用插件选项 Schema 自动生成 docs/plugin-options.md。这意味着文档与 Schema 单源同步,新增选项不会出现文档遗漏。

gatsby develop的开发体验特性

本地开发时,插件会周期性检查 WP 侧的数据或 Schema 事件并自动响应,无需重启即可实时更新数据/Schema。核心实现在 src/steps/source-nodes/update-nodes/content-update-interval.js:

  • checkForNodeUpdates先暂停轮询,读取上次抓取时间(since = lastCompletedSourceTime - 500),发起一次 GraphQL 请求查询actionMonitorActions
  • 若有新事件,则通过emitter.emit("WEBHOOK_RECEIVED")触发刷新(重新运行 Schema 定制与sourceNodes);若无事件,则更新LAST_COMPLETED_SOURCE_TIME并恢复轮询;
  • 轮询间隔由develop.nodeUpdateInterval选项控制(默认5000ms,见 declare-plugin-options-schema.js)。

此外,ingestRemoteSchema在开发模式下有10 秒节流Date.now() - lastIngestRemoteSchemaTime <= 10000时直接返回,见 src/steps/ingest-remote-schema/index.js),防止同时收到大量 webhook 时反复摄取 Schema 造成抖动。

WPGatsby

WPGatsby(WordPress 侧插件)承担两大职责:

  1. 存储并向 Gatsby 暴露 WP 变更事件,供 Gatsby 查询后更新数据/Schema;
  2. 向 WPGraphQL Schema 添加若干附加字段(如schemaMd5wpGatsbyCompatibility兼容性 API 字段),这些是源插件运行所必需的。

Preview:预览机制

Preview 逻辑一部分在 WPGatsby,一部分在本插件。WPGatsby 拥有自己的 preview loader 逻辑,与 WP 端的 Gatsby 进程双向通信;插件侧全部 Preview 逻辑位于 src/steps/preview,详细说明见其中的 preview.md。核心流程可概括为:

  1. 用户在 WP 后台点击 "preview";
  2. WPGatsby 对每次save_post按帖去抖(同一帖 5 秒内多个 webhook 只发一个),并向 Preview 实例 POST 一个 webhook,携带:JWT 令牌(Gatsby 用它查询私有预览修订数据)、修订的父级数据库 id、是否为新建草稿、被预览节点类型、修订 id、WP 实例 URL、是否禁用修订、节点修改时间、以及preview: true标记;
  3. Gatsby 侧收到刷新 webhook 后,sourceNodes检测到 preview 标记,转而调用sourcePreviews(见 src/steps/source-nodes/index.ts),通过 WPGraphQL 的asPreviewAPI 抓取预览节点并更新 Gatsby 节点;
  4. onCreatePage阶段的两个函数协同:onCreatepageSavePreviewNodeIdToPageDependency在预览模式下建立"节点 id → 页面"映射(因此文档强调:任何希望可预览的页面都必须在pageContext中放入节点 id);onCreatePageRespondToPreviewStatusQuery在页面创建完成时把PREVIEW_SUCCESS状态回传给 WPGatsby;
  5. 未能在onCreatePage触发的残留回调,在onPreExtractQueries阶段以NO_PAGE_CREATED_FOR_PREVIEWED_NODE状态统一回传;runSteps的错误边界则会把出错回调标记为GATSBY_PREVIEW_PROCESS_ERROR
  6. Preview 前端在 45 秒超时后显示加载警告,并提供 "cancel and troubleshoot" 调试入口。

一个值得称道的性能优化:Preview 路径移除了抓取前对本地/远程 Schema 的 diff,改为先尝试更新、捕获 GraphQL 错误后再重新 diff Schema——这意味着在 WPGraphQL 中删除字段不会破坏 Preview,除非该 Preview 恰好查询了那个字段。同样的思路后来推广到了整个gatsby develop:收到 WPGatsby action 后先 diff Schema,若不同则重跑createSchemaCustomization,因此更新远程 Schema 后无需重启 Preview 或gatsby develop

文件处理:MediaItem 与 File 两种节点

插件中有两种相关的文件节点类型:

  • MediaItem:包含媒体文件元信息的 WPGraphQL 节点(如mediaDetailssourceUrl等);
  • File:Gatsby 的 file 节点类型,挂在MediaItem.localFile上。

关键设计:

  • MediaItem节点只在被其他节点通过 GraphQL connection 引用时才抓取(见 fetch-referenced-media-items.js),避免抓取管理员上传但从未使用的海量文件;
  • 本地File节点作为抓取MediaItem节点的副作用产生,通过beforeChangeNode插件选项接入(WpMediaItem默认选项定义在 src/models/gatsby-api.ts);
  • 由于预先掌握全部在用的 MediaItem id,这些请求无需分页,可以任意并发级别并行化,并能在请求队列尾部重试失败请求;
  • lazyNodes选项:某些场景下用户不想抓取所有MediaItem上的File节点,此时把type.MediaItem.lazyNodes设为trueFile节点改为在GraphQL resolver 中惰性抓取(而非 sourceNodes API 阶段),对应 src/models/gatsby-api.ts 的默认选项与 transform-object.js 中的 resolver 实现;
  • MediaItem.localFile子选项还支持excludeByMimeTypes(按 MIME 类型排除)、maxFileSizeBytes(默认 15MB,15728640字节)、requestConcurrency(默认 100,见 gatsby-api.ts)。

HTML 处理

节点数据中的 HTML 通过正则查找/替换在"每个节点的 JSON 字符串化结果"上统一处理(而非逐字段递归遍历,因为复杂数据结构下逐字段遍历的性能代价很大)。核心实现在 src/steps/source-nodes/create-nodes/process-node.js(该文件还包含 GatsbyImage 占位图 URL 的推导逻辑getPlaceholderUrlFromMediaItemNode)。处理的内容包括:

  • 指向 WP 的锚点链接改为相对链接;
  • 文件链接(CSSbackground-image、指向文件的锚点等)转换为静态 Gatsby 文件;
  • <img>标签转换为使用静态文件的 Gatsby 图片;
  • 支持自定义正则查找/替换任意字符串。

处理过程中,插件会按需抓取MediaItem节点(如果按 URL 能找到)和/或File节点(按MediaItem.sourceUrl或 HTML 中的 URL 查找)。

非节点 Root 字段

除节点外,插件还会抓取"能合理抓取"的根字段(如 ACF options)。任何需要输入参数的字段会被自动跳过。这些字段在每次数据更新时都会重新抓取——因为不挂在节点上的数据无法用 WPGatsby 事件描述变更。实现在 src/steps/source-nodes/create-nodes/fetch-and-create-non-node-root-fields.js:它用remoteSchema.nonNodeQuery查询 WPGraphQL,把结果包装成一个 id 为`${pluginOptions.url}--rootfields`的单一节点(typeName 为schema.typePrefix),并通过createNodeWithSideEffects创建。

总结

从架构上看,gatsby-source-wordpress的设计可以用三个关键词概括:

  1. 单次 introspection、双阶段复用:同一次远程 Schema introspection 同时服务于查询生成与 Schema 定制,并通过"已抓取类型才可查询""字段自动前缀""Schema MD5 diff"三者保证两端严格一致;
  2. 分层缓存对抗不确定性:Schema MD5 diff 解决"Schema 变了没"、ActionMonitor 解决"数据变了没"、硬缓存解决"Gatsby 缓存清了没",三层机制分别应对生产增量、开发实时性与本地 DX;
  3. 按需抓取 + 队列重试:MediaItem/File 只在被引用时抓取,配合"队列尾部重试"策略解决大型站点(2 万+ 节点)的抓取可靠性问题。

理解这份架构,无论是阅读 src/steps 源码、调试抓取异常,还是二次开发自己的 GraphQL 源插件,都会事半功倍。

  • 前端
  • 静态站点
  • Web框架

【免费下载链接】gatsby

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

项目地址:https://gitcode.com/gh_mirrors/ga/gatsby
点击查看免费下载
上一篇:three.js 核心 API 精讲:InstancedInterleavedBuffer 实例化交错缓冲区完全指南
下一篇:5分钟掌握Pose-Search:如何用人体姿态实现智能图像搜索

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

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

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

立即咨询