菜单

数据层

相关源文件

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

Redux 存储

Gatsby 使用 Redux 作为其内存数据库来存储所有节点和其他状态信息。Redux 存储包含用于数据层不同方面的各种切片。

Redux 存储会跨构建持久化到磁盘,以支持增量构建,并且关键状态切片如 nodescomponentspages 会被缓存。

来源: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

Source 阶段

  1. Source 插件从外部源提取数据
  2. 插件调用 createNode 操作将数据添加到存储中
  3. 如果存在 ID 相同的节点,Gatsby 会通过比较内容摘要来检测其是否已更改。

来源:packages/gatsby/src/redux/actions/public.js677-740

Schema 阶段

  1. Gatsby 允许通过 createTypescreateFieldExtension 等 API 进行模式自定义
  2. 如果未显式定义,Gatsby 会从节点数据形状推断 GraphQL 类型
  3. Gatsby构建 GraphQL 模式,其中包含所有节点及其关系

来源:packages/gatsby/src/schema/resolvers.ts23-42

Query 阶段

  1. Gatsby 在(构建时)从页面组件中提取 GraphQL 查询
  2. GraphQL runner 根据模式执行这些查询
  3. Node Model 解析字段并跟踪依赖项
  4. 查询结果存储为页面数据

来源: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

操作数据层时的关键API

节点创建和修改

  • createNode:向数据存储添加一个节点
  • createNodeField:向现有节点添加一个字段(常由转换插件使用)
  • touchNode:标记一个节点为当前构建中“已触碰”(防止垃圾回收)
  • deleteNode:从存储中移除一个节点

来源: packages/gatsby/src/redux/actions/public.js677-740 packages/gatsby/src/redux/actions/public.js550-581

数据查询

  • GraphQL查询:在页面组件中使用,以检索渲染所需的数据
  • useStaticQuery:用于从任何组件查询数据的React Hook
  • <StaticQuery>:用于在页面组件外部查询数据的组件

来源: packages/gatsby/index.d.ts79 packages/gatsby/index.d.ts60-79

性能考量

数据层在设计上注重性能,但也存在一些需要考虑的因素:

  1. 节点数量:数以万计的节点会减慢构建速度。
  2. 查询复杂度:复杂的GraphQL查询会影响构建性能。
  3. 内存使用:大量数据集在构建期间需要更多内存。

为了优化性能:

  • 使用实现高效数据源的适当源插件。
  • 通过在源头过滤数据来限制节点数量。
  • 在GraphQL查询中使用limitskip参数来分页大量数据集。
  • 通过持久化缓存来利用Gatsby的增量构建。

来源: packages/gatsby/src/query/__tests__/data-tracking.js1-27 packages/gatsby/src/utils/flags.ts101-109

结论

Gatsby数据层为从各种来源获取、转换和查询数据提供了一个强大的基础。通过抽象数据获取和处理的复杂性,它使开发人员能够通过统一的GraphQL接口专注于构建站点。数据层的缓存和依赖跟踪功能实现了Gatsby的增量构建,显著提高了内容更新时的构建性能。