diff --git a/packages/gatsby-transformer-remark/src/__tests__/on-node-create.js b/packages/gatsby-transformer-remark/src/__tests__/on-node-create.js index 7a085101225d6..4663c596d9059 100644 --- a/packages/gatsby-transformer-remark/src/__tests__/on-node-create.js +++ b/packages/gatsby-transformer-remark/src/__tests__/on-node-create.js @@ -1,6 +1,6 @@ const Promise = require(`bluebird`) const _ = require(`lodash`) -const onCreateNode = require(`../on-node-create`) +const { onCreateNode } = require(`../on-node-create`) const { graphql } = require(`gatsby/graphql`) const { createContentDigest } = require(`gatsby-core-utils`) diff --git a/packages/gatsby-transformer-remark/src/gatsby-node.js b/packages/gatsby-transformer-remark/src/gatsby-node.js index a9d2f96599009..7330ef19ea39c 100644 --- a/packages/gatsby-transformer-remark/src/gatsby-node.js +++ b/packages/gatsby-transformer-remark/src/gatsby-node.js @@ -1,5 +1,10 @@ +const { + onCreateNode, + unstable_shouldOnCreateNode, +} = require(`./on-node-create`) +exports.onCreateNode = onCreateNode +exports.unstable_shouldOnCreateNode = unstable_shouldOnCreateNode exports.createSchemaCustomization = require(`./create-schema-customization`) -exports.onCreateNode = require(`./on-node-create`) exports.setFieldsOnGraphQLNodeType = require(`./extend-node-type`) if (process.env.GATSBY_EXPERIMENTAL_PLUGIN_OPTION_VALIDATION) { diff --git a/packages/gatsby-transformer-remark/src/on-node-create.js b/packages/gatsby-transformer-remark/src/on-node-create.js index f2b2dc841213c..b47dce011f945 100644 --- a/packages/gatsby-transformer-remark/src/on-node-create.js +++ b/packages/gatsby-transformer-remark/src/on-node-create.js @@ -1,7 +1,14 @@ const grayMatter = require(`gray-matter`) const _ = require(`lodash`) -module.exports = async function onCreateNode( +function unstable_shouldOnCreateNode({ node }) { + return ( + node.internal.mediaType === `text/markdown` || + node.internal.mediaType === `text/x-markdown` + ) +} + +module.exports.onCreateNode = async function onCreateNode( { node, loadNodeContent, @@ -15,10 +22,7 @@ module.exports = async function onCreateNode( const { createNode, createParentChildLink } = actions // We only care about markdown content. - if ( - node.internal.mediaType !== `text/markdown` && - node.internal.mediaType !== `text/x-markdown` - ) { + if (!unstable_shouldOnCreateNode({ node })) { return {} } @@ -76,3 +80,5 @@ module.exports = async function onCreateNode( return {} // eslint } } + +module.exports.unstable_shouldOnCreateNode = unstable_shouldOnCreateNode diff --git a/packages/gatsby-transformer-sharp/src/gatsby-node.js b/packages/gatsby-transformer-sharp/src/gatsby-node.js index 53ea07b51a701..81be7827f5a02 100644 --- a/packages/gatsby-transformer-sharp/src/gatsby-node.js +++ b/packages/gatsby-transformer-sharp/src/gatsby-node.js @@ -1,3 +1,8 @@ -exports.onCreateNode = require(`./on-node-create`) +const { + onCreateNode, + unstable_shouldOnCreateNode, +} = require(`./on-node-create`) +exports.onCreateNode = onCreateNode +exports.unstable_shouldOnCreateNode = unstable_shouldOnCreateNode exports.createSchemaCustomization = require(`./customize-schema`) exports.createResolvers = require(`./create-resolvers`) diff --git a/packages/gatsby-transformer-sharp/src/on-node-create.js b/packages/gatsby-transformer-sharp/src/on-node-create.js index 7590d4fd9abc7..30d319187cbf3 100644 --- a/packages/gatsby-transformer-sharp/src/on-node-create.js +++ b/packages/gatsby-transformer-sharp/src/on-node-create.js @@ -1,9 +1,17 @@ const { supportedExtensions } = require(`./supported-extensions`) -module.exports = async function onCreateNode({ node, actions, createNodeId }) { +function unstable_shouldOnCreateNode({ node }) { + return !!supportedExtensions[node.extension] +} + +module.exports.onCreateNode = async function onCreateNode({ + node, + actions, + createNodeId, +}) { const { createNode, createParentChildLink } = actions - if (!supportedExtensions[node.extension]) { + if (!unstable_shouldOnCreateNode({ node })) { return } @@ -22,3 +30,5 @@ module.exports = async function onCreateNode({ node, actions, createNodeId }) { return } + +module.exports.unstable_shouldOnCreateNode = unstable_shouldOnCreateNode diff --git a/packages/gatsby/index.d.ts b/packages/gatsby/index.d.ts index b8a448defead3..5337a4d438fc0 100644 --- a/packages/gatsby/index.d.ts +++ b/packages/gatsby/index.d.ts @@ -306,6 +306,20 @@ export interface GatsbyNode { callback?: PluginCallback ): void + /** + * Called before scheduling a `onCreateNode` callback for a plugin. If it returns falsy + * then Gatsby will not schedule the `onCreateNode` callback for this node for this plugin. + * Note: this API does not receive the regular `api` that other callbacks get as first arg. + * + * @gatsbyVersion 2.24.80 + * @example + * exports.unstable_shouldOnCreateNode = ({node}, pluginOptions) => node.internal.type === 'Image' + */ + unstable_shouldOnCreateNode?( + args: { node: TNode }, + options?: PluginOptions + ): boolean + /** * Called when a new page is created. This extension API is useful * for programmatically manipulating pages created by other plugins e.g. diff --git a/packages/gatsby/scripts/__tests__/api.js b/packages/gatsby/scripts/__tests__/api.js index a105112d831d5..105f3c9ab04f9 100644 --- a/packages/gatsby/scripts/__tests__/api.js +++ b/packages/gatsby/scripts/__tests__/api.js @@ -59,6 +59,9 @@ it("generates the expected api output", done => { "resolvableExtensions": Object {}, "setFieldsOnGraphQLNodeType": Object {}, "sourceNodes": Object {}, + "unstable_shouldOnCreateNode": Object { + "version": "2.24.80", + }, }, "ssr": Object { "onPreRenderHTML": Object {}, diff --git a/packages/gatsby/src/utils/api-node-docs.ts b/packages/gatsby/src/utils/api-node-docs.ts index 2d9e35d00a983..8de789cb8db2a 100644 --- a/packages/gatsby/src/utils/api-node-docs.ts +++ b/packages/gatsby/src/utils/api-node-docs.ts @@ -133,6 +133,17 @@ export const sourceNodes = true */ export const onCreateNode = true +/** + * Called before scheduling a `onCreateNode` callback for a plugin. If it returns falsy + * then Gatsby will not schedule the `onCreateNode` callback for this node for this plugin. + * Note: this API does not receive the regular `api` that other callbacks get as first arg. + * + * @gatsbyVersion 2.24.80 + * @example + * exports.unstable_shouldOnCreateNode = ({node}, pluginOptions) => node.internal.type === 'Image' + */ +export const unstable_shouldOnCreateNode = true + /** * Called when a new page is created. This extension API is useful * for programmatically manipulating pages created by other plugins e.g. diff --git a/packages/gatsby/src/utils/api-runner-node.js b/packages/gatsby/src/utils/api-runner-node.js index 43ca6a498ef8c..b4ea0c5e95b02 100644 --- a/packages/gatsby/src/utils/api-runner-node.js +++ b/packages/gatsby/src/utils/api-runner-node.js @@ -527,9 +527,28 @@ module.exports = async (api, args = {}, { pluginSource, activity } = {}) => return null } + let gatsbyNode = pluginNodeCache.get(plugin.name) + if (!gatsbyNode) { + gatsbyNode = require(`${plugin.resolve}/gatsby-node`) + pluginNodeCache.set(plugin.name, gatsbyNode) + } + const pluginName = plugin.name === `default-site-plugin` ? `gatsby-node.js` : plugin.name + // TODO: rethink createNode API to handle this better + if ( + api === `onCreateNode` && + gatsbyNode?.unstable_shouldOnCreateNode && // Don't bail if this api is not exported + !gatsbyNode.unstable_shouldOnCreateNode( + { node: args.node }, + plugin.pluginOptions + ) + ) { + // Do not try to schedule an async event for this node for this plugin + return null + } + return new Promise(resolve => { resolve(runAPI(plugin, api, { ...args, parentSpan: apiSpan }, activity)) }).catch(err => {