diff --git a/packages/docusaurus-mdx-loader/src/loader.ts b/packages/docusaurus-mdx-loader/src/loader.ts index f87a19e4872c..3aa7fc35ba54 100644 --- a/packages/docusaurus-mdx-loader/src/loader.ts +++ b/packages/docusaurus-mdx-loader/src/loader.ts @@ -218,6 +218,7 @@ export async function mdxLoader( const compilerName = getWebpackLoaderCompilerName(this); const callback = this.async(); const options: Options = this.getOptions(); + options.dependencies?.forEach(this.addDependency); try { const result = await loadMDXWithCaching({ resource: this.resource, diff --git a/packages/docusaurus-mdx-loader/src/options.ts b/packages/docusaurus-mdx-loader/src/options.ts index ed199dc4afab..5190953b0a0b 100644 --- a/packages/docusaurus-mdx-loader/src/options.ts +++ b/packages/docusaurus-mdx-loader/src/options.ts @@ -11,6 +11,8 @@ import type {ResolveMarkdownLink} from './remark/resolveMarkdownLinks'; import type {PromiseWithResolvers} from './utils'; export type Options = Partial & { + dependencies?: string[]; + markdownConfig: MarkdownConfig; staticDirs: string[]; siteDir: string; diff --git a/packages/docusaurus-plugin-content-docs/src/index.ts b/packages/docusaurus-plugin-content-docs/src/index.ts index fe72e070bb17..0d39e04e54ea 100644 --- a/packages/docusaurus-plugin-content-docs/src/index.ts +++ b/packages/docusaurus-plugin-content-docs/src/index.ts @@ -6,6 +6,7 @@ */ import path from 'path'; +import fs from 'fs-extra'; import _ from 'lodash'; import logger from '@docusaurus/logger'; import { @@ -63,6 +64,30 @@ import type {LoadContext, Plugin} from '@docusaurus/types'; import type {DocFile, FullVersion} from './types'; import type {RuleSetRule} from 'webpack'; +// MDX loader is not 100% deterministic, leading to cache invalidation issue +// This permits to invalidate the MDX loader cache entries when content changes +// Problem documented here: https://github.com/facebook/docusaurus/pull/10934 +// TODO this is not a perfect solution, find better? +async function createMdxLoaderDependencyFile({ + dataDir, + options, + versionsMetadata, +}: { + dataDir: string; + options: PluginOptions; + versionsMetadata: VersionMetadata[]; +}) { + const filePath = path.join(dataDir, '__mdx-loader-dependency.json'); + // the cache is invalidated whenever this file content changes + const fileContent = { + options, + versionsMetadata, + }; + await fs.ensureDir(dataDir); + await fs.writeFile(filePath, JSON.stringify(fileContent)); + return filePath; +} + export default async function pluginContentDocs( context: LoadContext, options: PluginOptions, @@ -107,6 +132,14 @@ export default async function pluginContentDocs( return createMDXLoaderRule({ include: contentDirs, options: { + dependencies: [ + await createMdxLoaderDependencyFile({ + dataDir, + options, + versionsMetadata, + }), + ], + useCrossCompilerCache: siteConfig.future.experimental_faster.mdxCrossCompilerCache, admonitions: options.admonitions,