Gatsby 数据层是使框架能够从各种数据源提取、转换和查询数据的 foundational subsystem。这个核心子系统管理来自外部 API、数据库、文件、CMS 等的数据摄取,通过 GraphQL 使它们统一可访问。它还负责数据缓存、依赖项跟踪,并实现 Gatsby 的增量构建。有关 GraphQL 实现的更多信息,请参阅GraphQL 引擎。
数据层由几个关键组件组成,这些组件协同工作以提供统一的数据管理系统。
来源:packages/gatsby/src/redux/types.ts269-297 packages/gatsby/src/schema/node-model.js64-166 packages/gatsby/cache-dir/loader.js70-90
Gatsby 数据层核心是节点存储系统。节点是 Gatsby 中的基本数据单元,代表内容、配置或任何其他数据的片段。
节点遵循一致的结构
{
id: String, // Unique identifier
internal: {
type: String, // Node type (e.g., "MarkdownRemark")
contentDigest: String, // Content hash for change detection
mediaType: String, // Optional MIME type
content: String, // Optional raw content
description: String // Optional human readable description
},
children: Array, // IDs of child nodes
parent: String, // ID of parent node (or null)
...customFields // Source-specific fields
}
来源:packages/gatsby/src/redux/types.ts147-162
Gatsby 使用 Redux 作为其内存数据库来存储所有节点和其他状态信息。Redux 存储包含用于数据层不同方面的各种切片。
Redux 存储会跨构建持久化到磁盘,以支持增量构建,并且关键状态切片如 nodes、components 和 pages 会被缓存。
来源:packages/gatsby/src/redux/index.ts18-35 packages/gatsby/src/redux/types.ts279-427
Node Model 提供了一个在数据层查询和跟踪节点的 API。它是 GraphQL 解析器用来检索数据的首要接口。
来源:packages/gatsby/src/schema/node-model.js65-620
NodeModel 提供了几种查询数据的方法
getNodeById:根据 ID 检索节点,可选择按类型过滤getNodesByIds:根据 ID 检索多个节点findOne:查找匹配指定查询的单个节点findAll:查找匹配指定查询的所有节点getTypes:返回存储中的所有节点类型示例用法(内部)
// Get a node by ID
const node = nodeModel.getNodeById({ id: `some-id` })
// Find nodes matching a filter
const { entries, totalCount } = await nodeModel.findAll({
query: {
filter: { published: { eq: true } },
sort: { date: `DESC` }
},
type: `BlogPost`
})
来源:packages/gatsby/src/schema/node-model.js136-357 packages/gatsby/src/schema/__tests__/node-model.js62-125
NodeModel 的一个关键方面是依赖项跟踪。当一个页面查询数据时,NodeModel 会记录页面使用了哪些节点。这使得 Gatsby 能够知道在数据发生变化时需要重建哪些页面。
来源:packages/gatsby/src/schema/node-model.js580-595 packages/gatsby/src/schema/__tests__/node-model.js166-201
理解 Gatsby 中数据的完整生命周期有助于解释数据层的功能。
来源:packages/gatsby/src/services/initialize.ts76-509 packages/gatsby/src/query/query-runner.ts30-147
createNode 操作将数据添加到存储中来源:packages/gatsby/src/redux/actions/public.js677-740
createTypes、createFieldExtension 等 API 进行模式自定义来源:packages/gatsby/src/schema/resolvers.ts23-42
来源:packages/gatsby/src/query/graphql-runner.ts47-139 packages/gatsby/src/utils/page-data.ts100-132
页面数据是每个页面 GraphQL 查询的输出,存储为 JSON 文件,供浏览器在渲染页面时获取。
来源:packages/gatsby/src/utils/page-data.ts28-36 packages/gatsby/cache-dir/loader.js73-89
来源: packages/gatsby/src/utils/page-data.ts100-132 packages/gatsby/cache-dir/production-app.js34-43
数据层的缓存机制实现了Gatsby的增量构建,显著缩短了内容更新时的构建时间。
Gatsby在构建之间将Redux store持久化到磁盘,重点关注以下关键切片:
nodes:所有内容节点components:组件元数据和查询pages:页面元数据staticQueryComponents:静态查询元数据当构建开始时,Gatsby会检查插件、gatsby-config.js或gatsby-node.js是否有更改。如果没有更改,它会重用缓存的Redux状态,以避免重新处理所有数据。
来源: packages/gatsby/src/redux/persist.ts23-51 packages/gatsby/src/services/initialize.ts333-365
当数据更改时,Gatsby会确定需要重新构建哪些页面。
来源: packages/gatsby/src/query/__tests__/data-tracking.js1-16
createNode:向数据存储添加一个节点createNodeField:向现有节点添加一个字段(常由转换插件使用)touchNode:标记一个节点为当前构建中“已触碰”(防止垃圾回收)deleteNode:从存储中移除一个节点来源: packages/gatsby/src/redux/actions/public.js677-740 packages/gatsby/src/redux/actions/public.js550-581
useStaticQuery:用于从任何组件查询数据的React Hook<StaticQuery>:用于在页面组件外部查询数据的组件来源: packages/gatsby/index.d.ts79 packages/gatsby/index.d.ts60-79
数据层在设计上注重性能,但也存在一些需要考虑的因素:
为了优化性能:
limit和skip参数来分页大量数据集。来源: packages/gatsby/src/query/__tests__/data-tracking.js1-27 packages/gatsby/src/utils/flags.ts101-109
Gatsby数据层为从各种来源获取、转换和查询数据提供了一个强大的基础。通过抽象数据获取和处理的复杂性,它使开发人员能够通过统一的GraphQL接口专注于构建站点。数据层的缓存和依赖跟踪功能实现了Gatsby的增量构建,显著提高了内容更新时的构建性能。