拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Gatsby Content Sync 内容同步机制全解析:从 CMS 预览到 Node Manifest 页面映射

Gatsby Content Sync 内容同步机制全解析从 CMS 预览到 Node Manifest 页面映射【免费下载链接】gatsbyReact-based framework with performance, scalability, and security built in.项目地址: https://gitcode.com/gh_mirrors/ga/gatsbyContent Sync 是 Gatsby Cloud 面向内容编辑者提供的核心功能它把 CMS 中Open Preview打开预览按钮与 Gatsby Preview 站点的正确页面无缝衔接起来编辑者点击预览后系统先展示加载状态构建完成后自动跳转到对应页面失败时则给出明确的错误提示。本文将基于当前仓库 docs/docs/conceptual/content-sync.md 的官方说明深入packages/gatsby源码完整讲解 Content Sync 的工作原理、Node 到 Page 的映射优先级、ownerNodeId手动指定方法以及源插件作者如何接入该能力帮助你快速定位预览路由问题或为自己的源插件开启 Content Sync 支持。什么是 Content SyncContent Sync 是Gatsby Cloud 的一项服务端功能专门用于改进 CMS 内容编辑者的 Preview预览体验。它的核心价值在于解决两个问题路由正确性编辑者在 CMS 中按下 Open Preview 时Content Sync 会把它们引导到正确的 URL——即使内容来自一个没有直接顶层页面的嵌套节点nested node也能被路由到正确的页面。状态可见性编辑者能够清楚了解预览的当前状态——内容何时可以查看、构建是否出现错误。其工作方式是当编辑者触发预览时Content Sync 先将用户重定向到一个等待室waiting room页面该页面在内容预览构建期间显示加载状态构建完成后自动将编辑者重定向到 Gatsby Preview 站点前端的正确页面。如果预览构建失败或者没有创建包含被预览内容的页面Content Sync 界面会显示错误消息并提供 View Error Logs 链接供编辑者查看构建错误日志。说明Content Sync 依赖 Node Manifest节点清单机制在 Gatsby 构建产物中留下路由线索这一机制的运行时实现位于packages/gatsby中下文会详细展开。端到端流程从点击预览到页面跳转文档中的 Diagram 给出了一条完整的时序链路结合仓库中 packages/gatsby/src/utils/node-manifest.ts 的实现可以还原出如下流程CMS 侧触发用户内容编辑者在 CMS 中点击 Open PreviewCMS 为该内容的当前修订状态生成一个唯一的Manifest ID并将请求发送到Preview Webhook。Gatsby Cloud 接收并构建Gatsby Cloud 收到 webhook 请求后启动一次构建站点通过 Content Sync ID 打开。加载等待Content Sync 界面显示加载状态Polishing your site同时检查 Gatsby 构建的public目录中是否存在匹配的 Manifest ID。Node Manifest 匹配构建过程中源插件调用unstable_createNodeManifest写入清单当 CMS 生成的 Manifest ID 与构建产物中的清单匹配成功时Gatsby 将数据映射到正确的预览页面并把 manifest 文件写入构建的public目录。持久化运行时检测Gatsby Cloud Preview Runner持久化运行时检测到待预览的 Node manifest确认预览就绪后重定向到预览页面本身。从源码看Node Manifest 文件会被写入站点的public/__node-manifests/pluginName/manifestId.json路径下见 processNodeManifest 的写入逻辑。每个 manifest 文件内容包含page找到的页面路径、node节点 id以及foundPageBy本次匹配所采用的映射方式三个字段——foundPageBy正是下文映射优先级的直接体现其取值类型在源码中定义为ownerNodeId、filesystem-route-api、context.id、context.slug、queryTracking、none六种见 packages/gatsby/src/utils/node-manifest.ts#L26-L33。清单文件数量与排序的工程细节源码中还有两个值得注意的工程细节写入上限默认最多写入10000个 manifest 文件可通过环境变量NODE_MANIFEST_FILE_LIMIT覆盖见 getNodeManifestFileLimit。按更新时间排序当 manifest 数量超过上限时会先按updatedAtUTC升序排序并截断优先保留已知较新的清单见 nodeManifestSortComparerAscendingUpdatedAt。并发处理所有待处理 manifest 通过fastq队列以并发度 25 批量写入磁盘并在结束后从 store 中清理见 processNodeManifests。为内容预览找到正确的页面多数情况下一个内容节点node只会对应一个页面Content Sync 可以自动完成映射。但当一个节点同时出现在多个页面时例如一篇博客文章既出现在文章详情页又出现在博客列表页系统可能把你路由到不想预览的页面上。此时可以通过createPageAPI 的ownerNodeId参数手动指定哪个节点拥有哪个页面将ownerNodeId设置为该节点在 Gatsby 中的node.id即可声明该页面归这个节点所有注意ownerNodeId必须对应一个通过 GraphQL 查询被包含在该页面上的节点。ownerNodeId在createPageaction 中的官方定义如下见 packages/gatsby/src/redux/actions/public.js#L166The id of the node that owns this page. This is used for routing users to previews via the unstable_createNodeManifest public action. Since multiple nodes can be queried on a single page, this allows the user to tell us which node is the main node for the page.一个完整的用法示例与 createPage 官方示例 一致// gatsby-node.js exports.createPages async ({ actions }) { const { createPage } actions createPage({ path: /my-sweet-new-page/, component: path.resolve(./src/templates/my-sweet-new-page.js), // 声明该页面由 id 为 123456 的节点“拥有” ownerNodeId: 123456, // context 会作为 props 传入组件并作为 GraphQL 查询参数 context: { id: 123456, }, }) }如果你使用File System Route API创建页面或者页面的context中已包含匹配的id属性则不需要手动设置ownerNodeId系统会自动完成映射详见下文映射优先级第 2、3 条。Node 到 Page 的映射优先级Mapping HierarchyContent Sync 的核心路由决策依赖unstable_createNodeManifestAPI源插件在sourceNodes阶段调用该 action 告诉 Gatsby哪些节点正在被预览。当这个公开 action 被调用时Gatsby 内部会按照一套从最具体到最不具体的优先级顺序来确定内容作者想预览的页面createPageaction 中的ownerNodeId属性由站点开发者手动设置——最具体通过 File System Route API 创建的页面所关联的节点自动匹配createPage传入的页面context中的id属性且该 id 与预览节点 id 匹配自动匹配Gatsby 的 GraphQL 查询跟踪query tracking中找到的第一个匹配节点 id——该映射把查询了某个节点 id 的页面与页面关联起来使得没有直接顶层页面的节点也能在站内被预览自动匹配最不具体。这套优先级在源码findPageOwnedByNode中有完整对应实现见 packages/gatsby/src/utils/node-manifest.ts#L61-L187且源码中还额外实现了一条文档里未展开的兜底规则context.slug匹配——如果节点带有slug字段且页面context.slug与之匹配也会被纳入候选见 packages/gatsby/src/utils/node-manifest.ts#L137-L153。源码注释说明GraphQL 查询中按node.slug查询足够常见因此作为ownerNodeId、File System Route、context.id之后的回退方案。优先级背后的实现细节ownerNodeId始终优先即使某个页面同时满足context.id/context.slug匹配只要站内存在一个页面将其ownerNodeId设置为该节点 id就一定会采用ownerNodeId匹配见 packages/gatsby/src/utils/node-manifest.ts#L116-L127。File System Route API 的判定方式当页面context.id匹配时源码会检查创建该页面的插件是否为gatsby-plugin-page-creator——是则标记为filesystem-route-api否则标记为context.id见 packages/gatsby/src/utils/node-manifest.ts#L142-L150。静态查询的特殊处理query tracking 可能返回以sq--开头的静态查询 id此时源码会通过静态查询组件路径回溯到使用该静态查询的第一个页面见 packages/gatsby/src/utils/node-manifest.ts#L93-L108。警告与错误码不同的映射方式对应不同的日志级别。ownerNodeId与filesystem-route-api视为成功success而context.id、context.slug、queryTracking、none会触发带错误 id 的警告见 foundPageByToLogIds错误 id 与packages/gatsby-cli/src/structured-errors/error-map.ts中的定义对应。源插件作者如何接入 Content Sync如果你是一个源插件source plugin的作者文档明确指出为你的源插件及其 CMS 扩展添加 Content Sync 支持的完整说明见 源插件作者文档仓库内对应路径为 docs/docs/how-to/plugins-and-themes/creating-a-source-plugin.md。接入的核心入口就是unstable_createNodeManifest这个公开 action。它在 packages/gatsby/src/redux/actions/public.js 中定义官方 JSDoc 给出了明确的参数契约参数类型说明manifestIdstring必填将 manifest 的唯一修订状态与数据源的唯一修订状态绑定在一起的 idnodeObject必填要绑定的 Gatsby 节点结构同createNode中的 node 对象至少要包含idupdatedAtUTCstring可选节点的最后更新时间。若不传则每个被调用的节点都会生成 manifest默认只为最近 30 天内更新的内容创建 manifest官方示例取自 packages/gatsby/src/redux/actions/public.js#L1426-L1433unstable_createNodeManifest({ manifestId: post-id-1--updated-53154315, updatedAtUTC: 2021-07-08T21:52:28.79101:00, node: { id: post-id-1, }, })环境变量与调试结合源码以下环境变量与 Content Sync 排查直接相关NODE_MANIFEST_MAX_DAYS_OLD默认只对最近 30 天更新的内容创建 manifest可借此变量调整窗口见 unstable_createNodeManifest 的 JSDoc。NODE_MANIFEST_FILE_LIMIT调整写入磁盘的 manifest 文件数量上限默认10000见 packages/gatsby/src/utils/node-manifest.ts#L37-L49。VERBOSE_NODE_MANIFESTtrue或gatsby_log_levelverbose开启 manifest 处理过程的详细日志。开启后processNodeManifests会输出已写入多少 manifest、耗时多少毫秒、多少个处理失败的统计信息并提示设置VERBOSE_NODE_MANIFEST查看完整警告见 packages/gatsby/src/utils/node-manifest.ts#L422-L424 与 L489-L508。需要特别说明Node manifest 文件在本地开发gatsby develop时也会被写入磁盘但一般不会派上用场——它们主要用于运行在 Gatsby Cloud 上的 Content Sync。此外源码注释还提到findPageOwnedByNode在gatsby develop下可能无法正常工作因为开发模式下页面查询并非全部执行node id 到页面的查询映射只有在浏览器访问过页面后才会存在见 packages/gatsby/src/utils/node-manifest.ts#L52-L60。常见问题排查速查预览被路由到了错误的页面例如详情页与列表页同时存在为该页面设置ownerNodeId明确声明页面归属。内容位于嵌套节点、没有对应顶层页面无需额外配置依赖映射优先级第 4 条query tracking即可在整个站点内找到查询了该节点的页面。预览一直停留在加载状态检查构建是否成功、manifest 是否写入public/__node-manifests目录以及 CMS 生成的 Manifest ID 是否与unstable_createNodeManifest的manifestId一致。想看构建期的映射细节设置VERBOSE_NODE_MANIFESTtrue重新构建观察Wrote out N node page manifest file(s)日志与警告中的错误 id。参考文档与相关资源本文主体Content Sync 概念文档createPage与unstable_createNodeManifestaction 定义packages/gatsby/src/redux/actions/public.jsNode Manifest 处理与页面映射实现packages/gatsby/src/utils/node-manifest.tsNode Manifest reducerpackages/gatsby/src/redux/reducers/node-manifest.ts相关参考文档Actions 参考、File System Route API、页面节点依赖、创建源插件【免费下载链接】gatsbyReact-based framework with performance, scalability, and security built in.项目地址: https://gitcode.com/gh_mirrors/ga/gatsby创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门