Skip to content

Commit

Permalink
perf(gatsby): do not call and iterate getAllNodes(File) for each file (
Browse files Browse the repository at this point in the history
  • Loading branch information
pvdz authored Jan 8, 2021
1 parent a8b516f commit a455a23
Showing 1 changed file with 45 additions and 30 deletions.
75 changes: 45 additions & 30 deletions packages/gatsby/src/schema/resolvers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import systemPath from "path"
import normalize from "normalize-path"
import _ from "lodash"
import {
GraphQLList,
GraphQLType,
Expand Down Expand Up @@ -29,6 +28,9 @@ import { IGatsbyNode } from "../redux/types"

type ResolvedLink = IGatsbyNode | Array<IGatsbyNode> | null

type nestedListOfStrings = Array<string | nestedListOfStrings>
type nestedListOfNodes = Array<IGatsbyNode | nestedListOfNodes>

export function findMany<TSource, TArgs>(
typeName: string
): GatsbyResolver<TSource, TArgs> {
Expand Down Expand Up @@ -353,15 +355,22 @@ export function fileByPath<TSource, TArgs>(
args,
context,
info
): Promise<any> {
): Promise<IGatsbyNode | nestedListOfNodes | null> {
const resolver = fieldConfig.resolve || context.defaultFieldResolver
const fieldValue = await resolver(source, args, context, {
...info,
from: options.from || info.from,
fromNode: options.from ? options.fromNode : info.fromNode,
})
const fieldValue: nestedListOfStrings = await resolver(
source,
args,
context,
{
...info,
from: options.from || info.from,
fromNode: options.from ? options.fromNode : info.fromNode,
}
)

if (fieldValue == null) return null
if (fieldValue == null) {
return null
}

// Find the File node for this node (we assume the node is something
// like markdown which would be a child node of a File node).
Expand All @@ -370,34 +379,40 @@ export function fileByPath<TSource, TArgs>(
node => node.internal && node.internal.type === `File`
)

const findLinkedFileNode = (relativePath: string): any => {
// Use the parent File node to create the absolute path to
// the linked file.
const fileLinkPath = normalize(
systemPath.resolve(parentFileNode.dir, relativePath)
)
async function queryNodesByPath(
relPaths: nestedListOfStrings
): Promise<nestedListOfNodes> {
const arr: nestedListOfNodes = []
for (let i = 0; i < relPaths.length; ++i) {
arr[i] = await (Array.isArray(relPaths[i])
? queryNodesByPath(relPaths[i] as nestedListOfStrings)
: queryNodeByPath(relPaths[i] as string))
}
return arr
}

// Use that path to find the linked File node.
const linkedFileNode = _.find(
context.nodeModel.getAllNodes({ type: `File` }),
n => n.absolutePath === fileLinkPath
)
return linkedFileNode
function queryNodeByPath(relPath: string): Promise<IGatsbyNode> {
return context.nodeModel.runQuery({
query: {
filter: {
absolutePath: {
eq: normalize(systemPath.resolve(parentFileNode.dir, relPath)),
},
},
},
firstOnly: true,
type: `File`,
})
}

return resolveValue(findLinkedFileNode, fieldValue)
if (Array.isArray(fieldValue)) {
return queryNodesByPath(fieldValue)
} else {
return queryNodeByPath(fieldValue)
}
}
}

function resolveValue(
resolve: (a: any) => any,
value: any | Array<any>
): any | Array<any> {
return Array.isArray(value)
? value.map(v => resolveValue(resolve, v))
: resolve(value)
}

function getProjectedField(
info: GraphQLResolveInfo,
fieldName: string
Expand Down

0 comments on commit a455a23

Please sign in to comment.