mirror of
https://github.com/facebook/docusaurus.git
synced 2025-06-06 12:52:31 +02:00
perf(mdx-loader): cache mdx/remark compiler instances (#4997)
* (mdx-loader) only create mdx compiler once per webpack config * type fixes * fix path * remove assertion * docs: add missing Tab/TabItem imports * fixup Co-authored-by: slorber <lorber.sebastien@gmail.com> Co-authored-by: Josh-Cena <sidachen2003@gmail.com>
This commit is contained in:
parent
bb55586c20
commit
949a72e6a5
3 changed files with 61 additions and 45 deletions
22
packages/docusaurus-mdx-loader/src/deps.d.ts
vendored
22
packages/docusaurus-mdx-loader/src/deps.d.ts
vendored
|
@ -10,19 +10,17 @@ declare module '@mdx-js/mdx' {
|
||||||
import type {Processor} from 'unified';
|
import type {Processor} from 'unified';
|
||||||
import type {RemarkOrRehypePlugin} from '@docusaurus/mdx-loader';
|
import type {RemarkOrRehypePlugin} from '@docusaurus/mdx-loader';
|
||||||
|
|
||||||
namespace mdx {
|
export interface Options {
|
||||||
interface Options {
|
filepath?: string;
|
||||||
filepath?: string;
|
skipExport?: boolean;
|
||||||
skipExport?: boolean;
|
wrapExport?: string;
|
||||||
wrapExport?: string;
|
remarkPlugins?: RemarkOrRehypePlugin[];
|
||||||
remarkPlugins?: RemarkOrRehypePlugin[];
|
rehypePlugins?: RemarkOrRehypePlugin[];
|
||||||
rehypePlugins?: RemarkOrRehypePlugin[];
|
|
||||||
}
|
|
||||||
|
|
||||||
function sync(content: string, options?: Options): string;
|
|
||||||
function createMdxAstCompiler(options?: Options): Processor;
|
|
||||||
function createCompiler(options?: Options): Processor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function sync(content: string, options?: Options): string;
|
||||||
|
export function createMdxAstCompiler(options?: Options): Processor;
|
||||||
|
export function createCompiler(options?: Options): Processor;
|
||||||
export default function mdx(
|
export default function mdx(
|
||||||
content: string,
|
content: string,
|
||||||
options?: mdx.Options,
|
options?: mdx.Options,
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
import mdx from '@mdx-js/mdx';
|
import {createCompiler} from '@mdx-js/mdx';
|
||||||
import logger from '@docusaurus/logger';
|
import logger from '@docusaurus/logger';
|
||||||
import emoji from 'remark-emoji';
|
import emoji from 'remark-emoji';
|
||||||
import {
|
import {
|
||||||
|
@ -23,11 +23,18 @@ import transformImage from './remark/transformImage';
|
||||||
import transformLinks from './remark/transformLinks';
|
import transformLinks from './remark/transformLinks';
|
||||||
import type {MDXOptions} from '@docusaurus/mdx-loader';
|
import type {MDXOptions} from '@docusaurus/mdx-loader';
|
||||||
import type {LoaderContext} from 'webpack';
|
import type {LoaderContext} from 'webpack';
|
||||||
|
import type {Processor} from 'unified';
|
||||||
|
|
||||||
const {
|
const {
|
||||||
loaders: {inlineMarkdownImageFileLoader},
|
loaders: {inlineMarkdownImageFileLoader},
|
||||||
} = getFileLoaderUtils();
|
} = getFileLoaderUtils();
|
||||||
|
|
||||||
|
const pragma = `
|
||||||
|
/* @jsxRuntime classic */
|
||||||
|
/* @jsx mdx */
|
||||||
|
/* @jsxFrag mdx.Fragment */
|
||||||
|
`;
|
||||||
|
|
||||||
const DEFAULT_OPTIONS: MDXOptions = {
|
const DEFAULT_OPTIONS: MDXOptions = {
|
||||||
rehypePlugins: [],
|
rehypePlugins: [],
|
||||||
remarkPlugins: [unwrapMdxCodeBlocks, emoji, headings, toc],
|
remarkPlugins: [unwrapMdxCodeBlocks, emoji, headings, toc],
|
||||||
|
@ -35,6 +42,8 @@ const DEFAULT_OPTIONS: MDXOptions = {
|
||||||
beforeDefaultRehypePlugins: [],
|
beforeDefaultRehypePlugins: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const compilerCache = new Map<string | Options, [Processor, Options]>();
|
||||||
|
|
||||||
type Options = MDXOptions & {
|
type Options = MDXOptions & {
|
||||||
staticDirs: string[];
|
staticDirs: string[];
|
||||||
siteDir: string;
|
siteDir: string;
|
||||||
|
@ -124,38 +133,47 @@ export default async function mdxLoader(
|
||||||
|
|
||||||
const hasFrontMatter = Object.keys(frontMatter).length > 0;
|
const hasFrontMatter = Object.keys(frontMatter).length > 0;
|
||||||
|
|
||||||
const options: Options = {
|
if (!compilerCache.has(this.query)) {
|
||||||
...reqOptions,
|
const options: Options = {
|
||||||
remarkPlugins: [
|
...reqOptions,
|
||||||
...(reqOptions.beforeDefaultRemarkPlugins ?? []),
|
remarkPlugins: [
|
||||||
...DEFAULT_OPTIONS.remarkPlugins,
|
...(reqOptions.beforeDefaultRemarkPlugins ?? []),
|
||||||
[
|
...DEFAULT_OPTIONS.remarkPlugins,
|
||||||
transformImage,
|
[
|
||||||
{
|
transformImage,
|
||||||
staticDirs: reqOptions.staticDirs,
|
{
|
||||||
siteDir: reqOptions.siteDir,
|
staticDirs: reqOptions.staticDirs,
|
||||||
},
|
siteDir: reqOptions.siteDir,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
transformLinks,
|
||||||
|
{
|
||||||
|
staticDirs: reqOptions.staticDirs,
|
||||||
|
siteDir: reqOptions.siteDir,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
...(reqOptions.remarkPlugins ?? []),
|
||||||
],
|
],
|
||||||
[
|
rehypePlugins: [
|
||||||
transformLinks,
|
...(reqOptions.beforeDefaultRehypePlugins ?? []),
|
||||||
{
|
...DEFAULT_OPTIONS.rehypePlugins,
|
||||||
staticDirs: reqOptions.staticDirs,
|
...(reqOptions.rehypePlugins ?? []),
|
||||||
siteDir: reqOptions.siteDir,
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
...(reqOptions.remarkPlugins ?? []),
|
};
|
||||||
],
|
compilerCache.set(this.query, [createCompiler(options), options]);
|
||||||
rehypePlugins: [
|
}
|
||||||
...(reqOptions.beforeDefaultRehypePlugins ?? []),
|
|
||||||
...DEFAULT_OPTIONS.rehypePlugins,
|
const [compiler, options] = compilerCache.get(this.query)!;
|
||||||
...(reqOptions.rehypePlugins ?? []),
|
|
||||||
],
|
|
||||||
filepath: filePath,
|
|
||||||
};
|
|
||||||
|
|
||||||
let result: string;
|
let result: string;
|
||||||
try {
|
try {
|
||||||
result = await mdx(content, options);
|
result = await compiler
|
||||||
|
.process({
|
||||||
|
contents: content,
|
||||||
|
path: this.resourcePath,
|
||||||
|
})
|
||||||
|
.then((res) => res.toString());
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return callback(err as Error);
|
return callback(err as Error);
|
||||||
}
|
}
|
||||||
|
@ -214,6 +232,7 @@ ${assets ? `export const assets = ${createAssetsExportCode(assets)};` : ''}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const code = `
|
const code = `
|
||||||
|
${pragma}
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { mdx } from '@mdx-js/react';
|
import { mdx } from '@mdx-js/react';
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type {Code, Content, Literal} from 'mdast';
|
import type {Code, Content, Literal} from 'mdast';
|
||||||
import type {Plugin, Transformer} from 'unified';
|
import type {Plugin} from 'unified';
|
||||||
import type {Node, Parent} from 'unist';
|
import type {Node, Parent} from 'unist';
|
||||||
import visit from 'unist-util-visit';
|
import visit from 'unist-util-visit';
|
||||||
import npmToYarn from 'npm-to-yarn';
|
import npmToYarn from 'npm-to-yarn';
|
||||||
|
@ -61,9 +61,9 @@ const nodeForImport: Literal = {
|
||||||
|
|
||||||
const plugin: Plugin<[PluginOptions?]> = (options = {}) => {
|
const plugin: Plugin<[PluginOptions?]> = (options = {}) => {
|
||||||
const {sync = false} = options;
|
const {sync = false} = options;
|
||||||
let transformed = false;
|
return (root) => {
|
||||||
let alreadyImported = false;
|
let transformed = false;
|
||||||
const transformer: Transformer = (root) => {
|
let alreadyImported = false;
|
||||||
visit(root, (node: Node) => {
|
visit(root, (node: Node) => {
|
||||||
if (isImport(node) && node.value.includes('@theme/Tabs')) {
|
if (isImport(node) && node.value.includes('@theme/Tabs')) {
|
||||||
alreadyImported = true;
|
alreadyImported = true;
|
||||||
|
@ -87,7 +87,6 @@ const plugin: Plugin<[PluginOptions?]> = (options = {}) => {
|
||||||
(root as Parent).children.unshift(nodeForImport);
|
(root as Parent).children.unshift(nodeForImport);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return transformer;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// To continue supporting `require('npm2yarn')` without the `.default` ㄟ(▔,▔)ㄏ
|
// To continue supporting `require('npm2yarn')` without the `.default` ㄟ(▔,▔)ㄏ
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue