Skip to content

Commit

Permalink
docs(gatsby-internals): update page -> node dependency tracking (#25606)
Browse files Browse the repository at this point in the history
* docs(gatsby-internals): update page -> node dependency tracking

* Apply suggestions from code review

Co-authored-by: Aisha Blake <aisha@gatsbyjs.com>
  • Loading branch information
2 people authored and KyleAMathews committed Jul 29, 2020
1 parent 50b78a4 commit 3a88f91
Showing 1 changed file with 19 additions and 24 deletions.
43 changes: 19 additions & 24 deletions docs/docs/page-node-dependencies.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,33 @@
title: Page -> Node Dependency Tracking
---

> This documentation isn't up to date with the latest [schema customization changes](/docs/schema-customization).
>
> Outdated areas are:
>
> - `createPageDependency` is not the only way to mutate dependencies now
> - other helpers exist now
>
> You can help by making a PR to [update this documentation](https://github.com/gatsbyjs/gatsby/issues/14228).
In almost every GraphQL Resolver, you'll see the [createPageDependency](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/src/redux/actions/add-page-dependency.ts#L5), or [getNodeAndSavePathDependency](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/src/redux/nodes.ts#L108) functions. These are responsible for recording which nodes are depended on by which pages. In `develop` mode, when a node's content is changed the pages whose queries depend on that node will be re-run. This is one of the things that makes `develop` so awesome.
Gatsby keeps a record of used nodes for each query result. This makes it possible to cache and reuse results from previous runs if used nodes didn't change and, conversely, is used to determine which query results are stale and need to be rerun.

## How dependencies are recorded

Recording of Page -> Node dependencies are handled by the [createPageDependency](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/src/redux/actions/add-page-dependency.ts#L5) action. It takes the page (in the form of its `path`), and either a `nodeId`, or `connection`.
### `CREATE_COMPONENT_DEPENDENCY` action and `createPageAction` action creator

The internal `CREATE_COMPONENT_DEPENDENCY` action handles the recording of Page -> Node dependencies. It takes the `path` (page path for page queries or internal id for static queries), and either a `nodeId`, or `connection`.

Passing `nodeId` tells Gatsby that the page depends specifically on this node. So, if the node is changed, then the page's query needs to be re-executed.

`connection` is a Type string. E.g. `MarkdownRemark`, or `File`. Calling `createPageDependency` with a page path and a `connection` tells Gatsby that this page depends on all nodes of this type. Therefore if any node of this type changes (e.g. a change to a markdown node), then this page must be rebuilt. This variant is only called from [run-sift.js](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/src/redux/run-sift.js) when a query such as `allFile`, or `allMarkdownRemark` is run. See [Schema Connections](/docs/schema-connections/) for more info.
`connection` is a Type string. E.g. `MarkdownRemark`, or `File`. Calling `createPageDependency` with a `path` and a `connection` tells Gatsby that this page depends on all nodes of this type. Therefore if any node of this type changes (e.g. a change to a markdown node), then this page must be rebuilt. Using connection fields (e.g. `allMarkdownRemark`) is one of the cases when this variant is used.

`CREATE_COMPONENT_DEPENDENCY` action is conditionally dispatched by the internal `createPageAction` action creator. Action creator checks if we already have given dependencies stored to avoid emitting no-op actions. `createPageAction` is a low level internal API that is then used by higher level APIs.

### Higher level abstractions

#### Node Model

[Node Model](/docs/node-model/) is an API used in GraphQL resolvers to retrieve nodes from the data store. It's used internally in resolvers provided by Gatsby core and it can be used in resolvers provided by plugins via `context.nodeModel`. It calls `createPageAction` under the hood because Node Model is aware of the path of the query as well as the nodes being retrieved.

#### `getNodeAndSavePathDependency` helper

[`getNodeAndSavePathDependency`](/docs/node-api-helpers/#getNodeAndSavePathDependency) is a convenience wrapper around `getNode` and `createPageDependency`. It is not used internally. It's a legacy API for plugins to record data dependencies and is equivalent to `nodeModel.getNodeById`. The Node Model variant should be used instead as its API is less error prone. (Node Model is `path` aware and doesn't require you to pass it.)

## How dependencies are stored

Page -> Node dependencies are tracked via the `componentDataDependencies` redux namespace. `createPageDependency` is the only way to mutate it. The namespace is comprised of two sub structures:
Page -> Node dependencies are tracked via the `componentDataDependencies` redux namespace.

```javascript
{
Expand Down Expand Up @@ -62,14 +67,4 @@ Page -> Node dependencies are tracked via the `componentDataDependencies` redux

## How dependency information is used

Page -> Node dependencies are used entirely during query execution to figure out which nodes are "dirty", and therefore which page's queries need to be re-executed. This occurs in `query/index.js` in the [findIdsWithoutDataDependencies](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/src/query/index.js#L39) and [popNodeQueries](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/src/query/index.js#L71) functions. This is described in greater detail in the [Query Execution](/docs/query-execution/) docs.

## Other forms

### add-page-dependency.ts

[redux/actions/add-page-dependency.js](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/src/redux/actions/add-page-dependency.ts) is a wrapper around the `createPageDependency` action that performs some additional performance optimizations. It should be used instead of the raw action.

### getNodeAndSavePathDependency action

The [getNodeAndSavePathDependency](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/src/redux/nodes.ts#L108) action simply calls `getNode`, and then calls `createPageDependency` using that result. It is a programmer convenience.
Page -> Node dependencies are used entirely during query execution to figure out which nodes are "dirty" and to figure out which queries don't have any dependencies yet. "Dirty" nodes are used to determine which query results are stale and need to be re-executed. Finding queries without dependencies is used as a heuristic to determine which queries haven't run yet and therefore need to run.

0 comments on commit 3a88f91

Please sign in to comment.