Skip to content

Commit

Permalink
perf(gatsby): Shortcut trivial queries by id
Browse files Browse the repository at this point in the history
While there is a check for queries by `id`, this one circumvents a few more steps. It prevents having to build up an array based on type. Instead, if it sees a query by `id`, it will immediately just fetch that node directly.

This makes many sites that use plain queries by id a helluvalot faster. One site that made me look into this problem went down from 4.5 hours to about 5 minutes.
  • Loading branch information
pvdz committed Jan 14, 2020
1 parent 3e9bf07 commit ad345a8
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 2 deletions.
28 changes: 28 additions & 0 deletions packages/gatsby/src/redux/nodes.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,34 @@ exports.saveResolvedNodes = async (nodeTypeNames, resolver) => {
}
}

/**
* Get node and save path dependency.
*
* @param {string} typeName
* @param {string} id
* @returns {Object|void} node
*/
const getResolvedNode = (typeName, id) => {
const { nodesByType, resolvedNodesCache } = store.getState()
const nodes /*: Map<mixed> */ = nodesByType.get(typeName)

if (!nodes) return undefined

let node = nodes.get(id)

if (!node) return undefined

const resolvedNodes = resolvedNodesCache.get(typeName)

if (resolvedNodes) {
node.__gatsby_resolved = resolvedNodes.get(id)
}

return node
}

exports.getResolvedNode = getResolvedNode

const addResolvedNodes = (typeName, arr) => {
const { nodesByType, resolvedNodesCache } = store.getState()
const nodes /*: Map<mixed> */ = nodesByType.get(typeName)
Expand Down
19 changes: 17 additions & 2 deletions packages/gatsby/src/redux/run-sift.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ function handleMany(siftArgs, nodes, sort, resolvedFields) {
if (!result || !result.length) return null

// Sort results.
if (sort) {
if (sort && result.length > 1) {
// create functions that return the item to compare on
const dottedFields = objectToDottedField(resolvedFields)
const dottedFieldKeys = Object.keys(dottedFields)
Expand Down Expand Up @@ -123,9 +123,24 @@ function handleMany(siftArgs, nodes, sort, resolvedFields) {
* if `firstOnly` is true
*/
const runSift = (args: Object) => {
const { getNode, addResolvedNodes } = require(`./nodes`)
const { getNode, addResolvedNodes, getResolvedNode } = require(`./nodes`)

const { nodeTypeNames } = args
if (
args.queryArgs?.filter &&
Object.getOwnPropertyNames(args.queryArgs.filter).length === 1 &&
typeof args.queryArgs.filter?.id?.eq === `string`
) {
// The args have an id.eq which subsumes all other queries
// Since the id of every node is unique there can only ever be one node found this way. Find it and return it.
let id = args.queryArgs.filter.id.eq
let node = undefined
nodeTypeNames.some(typeName => {
node = getResolvedNode(typeName, id)
return !!node
})
if (node) return [node]
}

let nodes = []

Expand Down

0 comments on commit ad345a8

Please sign in to comment.