From 6d0c791e73ddb832f74023983fdad4a67de76d98 Mon Sep 17 00:00:00 2001 From: Peter van der Zee <209817+pvdz@users.noreply.github.com> Date: Fri, 17 Jul 2020 16:28:54 +0200 Subject: [PATCH] perf(gatsby-plugin-mdx): drop another babel step during sourcing (#25757) This Babel step was used to get exports and remark header but we can use the mdast for this purpose, just like for imports. See PR for perf numbers but they are big. --- .../gatsby/on-create-node.js | 17 +++---- .../gatsby-plugin-mdx/loaders/mdx-loader.js | 10 +++- .../loaders/mdx-loader.test.js | 4 +- .../utils/create-mdx-node.js | 49 +++++++++---------- packages/gatsby-plugin-mdx/utils/gen-mdx.js | 38 ++++++++------ 5 files changed, 66 insertions(+), 52 deletions(-) diff --git a/packages/gatsby-plugin-mdx/gatsby/on-create-node.js b/packages/gatsby-plugin-mdx/gatsby/on-create-node.js index b33d246c6f6d9..13cc593edc32c 100644 --- a/packages/gatsby-plugin-mdx/gatsby/on-create-node.js +++ b/packages/gatsby-plugin-mdx/gatsby/on-create-node.js @@ -6,7 +6,6 @@ const { createContentDigest } = require(`gatsby-core-utils`) const defaultOptions = require(`../utils/default-options`) const createMDXNode = require(`../utils/create-mdx-node`) const { MDX_SCOPES_LOCATION } = require(`../constants`) -const { findImports } = require(`../utils/gen-mdx`) const contentDigest = val => createContentDigest(val) @@ -18,6 +17,7 @@ module.exports = async ( createNodeId, getNode, getNodes, + getNodesByType, reporter, cache, pathPrefix, @@ -46,20 +46,14 @@ module.exports = async ( const content = await loadNodeContent(node) - const mdxNode = await createMDXNode({ + const { mdxNode, scopeIdentifiers, scopeImports } = await createMDXNode({ id: createNodeId(`${node.id} >>> Mdx`), node, content, - }) - createNode(mdxNode) - createParentChildLink({ parent: node, child: mdxNode }) - - // write scope files into .cache for later consumption - const { scopeImports, scopeIdentifiers } = await findImports({ - node: mdxNode, getNode, getNodes, + getNodesByType, reporter, cache, pathPrefix, @@ -69,6 +63,11 @@ module.exports = async ( createNodeId, ...helpers, }) + + createNode(mdxNode) + createParentChildLink({ parent: node, child: mdxNode }) + + // write scope files into .cache for later consumption await cacheScope({ cache, scopeIdentifiers, diff --git a/packages/gatsby-plugin-mdx/loaders/mdx-loader.js b/packages/gatsby-plugin-mdx/loaders/mdx-loader.js index 962090df3cec9..f82d3eebc8261 100644 --- a/packages/gatsby-plugin-mdx/loaders/mdx-loader.js +++ b/packages/gatsby-plugin-mdx/loaders/mdx-loader.js @@ -94,6 +94,7 @@ module.exports = async function (content) { const { getNode: rawGetNode, getNodes, + getNodesByType, reporter, cache, pathPrefix, @@ -121,11 +122,15 @@ module.exports = async function (content) { let mdxNode try { - mdxNode = await createMDXNode({ + // This node attempts to break the chicken-egg problem, where parsing mdx + // allows for custom plugins, which can receive a mdx node + ;({ mdxNode } = await createMDXNode({ id: `fakeNodeIdMDXFileABugIfYouSeeThis`, node: fileNode, content, - }) + options, + getNodesByType, + })) } catch (e) { return callback(e) } @@ -192,6 +197,7 @@ ${contentWithoutFrontmatter}` node: { ...mdxNode, rawBody: code }, getNode, getNodes, + getNodesByType, reporter, cache, pathPrefix, diff --git a/packages/gatsby-plugin-mdx/loaders/mdx-loader.test.js b/packages/gatsby-plugin-mdx/loaders/mdx-loader.test.js index 397e8c28ba308..6610550442e31 100644 --- a/packages/gatsby-plugin-mdx/loaders/mdx-loader.test.js +++ b/packages/gatsby-plugin-mdx/loaders/mdx-loader.test.js @@ -16,9 +16,9 @@ array: [1,2,3] )`, namedExports: `export const meta = {author: "chris"}`, body: `# Some title - + a bit of a paragraph - + some content`, } diff --git a/packages/gatsby-plugin-mdx/utils/create-mdx-node.js b/packages/gatsby-plugin-mdx/utils/create-mdx-node.js index 1071f9dbad46a..07c7f7d3c278e 100644 --- a/packages/gatsby-plugin-mdx/utils/create-mdx-node.js +++ b/packages/gatsby-plugin-mdx/utils/create-mdx-node.js @@ -1,20 +1,19 @@ const { createContentDigest } = require(`gatsby-core-utils`) -const mdx = require(`../utils/mdx`) -const extractExports = require(`../utils/extract-exports`) - -module.exports = async ({ id, node, content }) => { - let code - try { - code = await mdx(content) - } catch (e) { - // add the path of the file to simplify debugging error messages - e.message += `${node.absolutePath}: ${e.message}` - throw e - } - - // extract all the exports - const { frontmatter, ...nodeExports } = extractExports(code) +const { findImportsExports } = require(`../utils/gen-mdx`) + +async function createMdxNode({ id, node, content, ...helpers }) { + const { + frontmatter, + scopeImports, + scopeExports, + scopeIdentifiers, + } = await findImportsExports({ + mdxNode: node, + rawInput: content, + absolutePath: node.absolutePath, + ...helpers, + }) const mdxNode = { id, @@ -24,17 +23,15 @@ module.exports = async ({ id, node, content }) => { content: content, type: `Mdx`, }, + excerpt: frontmatter.excerpt, + exports: scopeExports, + rawBody: content, + frontmatter: { + title: ``, // always include a title + ...frontmatter, + }, } - mdxNode.frontmatter = { - title: ``, // always include a title - ...frontmatter, - } - - mdxNode.excerpt = frontmatter.excerpt - mdxNode.exports = nodeExports - mdxNode.rawBody = content - // Add path to the markdown file path if (node.internal.type === `File`) { mdxNode.fileAbsolutePath = node.absolutePath @@ -42,5 +39,7 @@ module.exports = async ({ id, node, content }) => { mdxNode.internal.contentDigest = createContentDigest(mdxNode) - return mdxNode + return { mdxNode, scopeIdentifiers, scopeImports } } + +module.exports = createMdxNode diff --git a/packages/gatsby-plugin-mdx/utils/gen-mdx.js b/packages/gatsby-plugin-mdx/utils/gen-mdx.js index 05c7df33cec80..dca1a25ce3c92 100644 --- a/packages/gatsby-plugin-mdx/utils/gen-mdx.js +++ b/packages/gatsby-plugin-mdx/utils/gen-mdx.js @@ -47,6 +47,7 @@ async function genMDX( options, getNode, getNodes, + getNodesByType, reporter, cache, pathPrefix, @@ -114,6 +115,7 @@ export const _frontmatter = ${JSON.stringify(data)}` // files, getNode, getNodes, + getNodesByType, reporter, cache, pathPrefix, @@ -194,8 +196,10 @@ ${code}` module.exports = genMDX // Legacy API, drop in v3 in favor of named export module.exports.genMDX = genMDX -async function findImports({ - node, +async function findImportsExports({ + mdxNode, + rawInput, + absolutePath = null, options, getNode, getNodes, @@ -205,12 +209,12 @@ async function findImports({ pathPrefix, ...helpers }) { - const { content } = grayMatter(node.rawBody) + const { data: frontmatter, content } = grayMatter(rawInput) const gatsbyRemarkPluginsAsremarkPlugins = await getSourcePluginsAsRemarkPlugins( { gatsbyRemarkPlugins: options.gatsbyRemarkPlugins, - mdxNode: node, + mdxNode, getNode, getNodes, getNodesByType, @@ -226,18 +230,19 @@ async function findImports({ ) const compilerOptions = { - filepath: node.fileAbsolutePath, + filepath: absolutePath, ...options, remarkPlugins: [ ...options.remarkPlugins, ...gatsbyRemarkPluginsAsremarkPlugins, ], } + const compiler = mdx.createCompiler(compilerOptions) const fileOpts = { contents: content } - if (node.fileAbsolutePath) { - fileOpts.path = node.fileAbsolutePath + if (absolutePath) { + fileOpts.path = absolutePath } const mdast = await compiler.parse(fileOpts) @@ -246,16 +251,19 @@ async function findImports({ // we don't need to dedupe the symbols here. const identifiers = [] const imports = [] + const exports = [] mdast.children.forEach(node => { - if (node.type !== `import`) return - - const importCode = node.value + if (node.type === `import`) { + const importCode = node.value - imports.push(importCode) + imports.push(importCode) - const bindings = parseImportBindings(importCode) - identifiers.push(...bindings) + const bindings = parseImportBindings(importCode) + identifiers.push(...bindings) + } else if (node.type === `export`) { + exports.push(node.value) + } }) if (!identifiers.includes(`React`)) { @@ -264,9 +272,11 @@ async function findImports({ } return { + frontmatter, scopeImports: imports, + scopeExports: exports, scopeIdentifiers: identifiers, } } -module.exports.findImports = findImports +module.exports.findImportsExports = findImportsExports