Gatsby调用touchNode处理页面节点时报TypeError: pageResources未定义
解决touchNode后访问缓存页面出现TypeError: locationAndPageResources.pageResources is undefined的问题
这个错误的核心原因是:你只touchNode了页面节点本身,但Gatsby缓存中与该页面关联的PageResources节点已经被垃圾回收机制清理了——Gatsby的页面渲染依赖页面节点和对应的PageResources(包含组件、数据等资源),两者缺一不可。
下面是具体的解决方案,按优先级排序:
1. 同时Touch页面节点和对应的PageResources节点
Gatsby中每个页面节点都会关联一个PageResources节点,你需要找到这个关联节点并一起touch,确保它不会被清理。修改你的代码如下:
await Promise.all(result.data.pages.map(async page => { const pageCacheKey = `cache-${page.url}` const cacheResult = await pageRecords.getKey(pageCacheKey) if (cacheResult) { const node = pageNodes.find(node => { if (!node.context) return return node.context.url == page.url }) if (node) { if (node.context.lastPublishedAt == page.lastPublishedAt) { pageRecords.setKey(pageCacheKey, localPublishedAt) // 找到对应的PageResources节点 const pageResources = getNodesByType(`PageResources`).find(pr => pr.page?.node?.id === node.id ); // 先touch页面节点,再touch资源节点 await touchNode({ nodeId: node.id }); if (pageResources) { await touchNode({ nodeId: pageResources.id }); } } } } }))
注意:getNodesByType是Gatsby API提供的方法,需要确保你的代码在支持该方法的API上下文(比如sourceNodes、onCreatePage)中运行。
2. 验证缓存键与资源关联的一致性
有时候缓存键的命名或匹配逻辑可能导致页面与资源的关联断裂,建议:
- 检查
pageCacheKey的生成逻辑是否唯一对应每个页面 - 确认
node.context.url与page.url的匹配逻辑没有大小写或路径格式的问题(比如末尾是否带斜杠)
3. 手动缓存PageResources作为兜底
如果上述方法仍有问题,可以通过Gatsby的缓存API手动保存PageResources的内容,确保它不会被清理:
if (node.context.lastPublishedAt == page.lastPublishedAt) { const pageResources = getNodesByType(`PageResources`).find(pr => pr.page?.node?.id === node.id ); // 缓存PageResources内容 if (pageResources) { await pageRecords.setKey(`${pageCacheKey}-resources`, JSON.stringify(pageResources)); } pageRecords.setKey(pageCacheKey, localPublishedAt); await touchNode({ nodeId: node.id }); if (pageResources) { await touchNode({ nodeId: pageResources.id }); } }
这样即使缓存意外清理,也可以从手动缓存中恢复PageResources(不过通常不需要这一步,除非你的缓存策略有特殊需求)。
内容的提问来源于stack exchange,提问作者Nathan Horrigan
相关产品推荐
相关产品推荐

