diff --git a/packages/docusaurus-theme-classic/src/index.ts b/packages/docusaurus-theme-classic/src/index.ts index f8a6d75d74..59d3ea5d3b 100644 --- a/packages/docusaurus-theme-classic/src/index.ts +++ b/packages/docusaurus-theme-classic/src/index.ts @@ -18,13 +18,13 @@ import type {Plugin as PostCssPlugin} from 'postcss'; import rtlcss from 'rtlcss'; import {readDefaultCodeTranslationMessages} from '@docusaurus/theme-translations'; import type {Options} from '@docusaurus/theme-classic'; +import type webpack from 'webpack'; const requireFromDocusaurusCore = createRequire( require.resolve('@docusaurus/core/package.json'), ); -const ContextReplacementPlugin = requireFromDocusaurusCore( - 'webpack/lib/ContextReplacementPlugin', -); +const ContextReplacementPlugin: typeof webpack.ContextReplacementPlugin = + requireFromDocusaurusCore('webpack/lib/ContextReplacementPlugin'); // Need to be inlined to prevent dark mode FOUC // Make sure that the 'storageKey' is the same as the one in `/theme/hooks/useTheme.js` @@ -172,6 +172,9 @@ export default function docusaurusThemeClassic( return { plugins: [ + // This allows better optimization by only bundling those components + // that the user actually needs, because the modules are dynamically + // required and can't be known during compile time. new ContextReplacementPlugin( /prismjs[\\/]components$/, new RegExp(`^./(${prismLanguages})$`), diff --git a/packages/docusaurus-theme-classic/src/theme/prism-include-languages.ts b/packages/docusaurus-theme-classic/src/theme/prism-include-languages.ts index 22a6238114..418e95dc3f 100644 --- a/packages/docusaurus-theme-classic/src/theme/prism-include-languages.ts +++ b/packages/docusaurus-theme-classic/src/theme/prism-include-languages.ts @@ -12,14 +12,21 @@ import type * as PrismNamespace from 'prismjs'; const prismIncludeLanguages = (PrismObject: typeof PrismNamespace): void => { if (ExecutionEnvironment.canUseDOM) { const { - themeConfig: {prism = {}}, + themeConfig: {prism}, } = siteConfig; - const {additionalLanguages = []} = prism as {additionalLanguages: string[]}; + const {additionalLanguages} = prism as {additionalLanguages: string[]}; + // Prism components work on the Prism instance on the window, while + // prism-react-renderer uses its own Prism instance. We temporarily mount + // the instance onto window, import components to enhance it, then remove it + // to avoid polluting global namespace. + // You can mutate this object: registering plugins, deleting languages... As + // long as you don't re-assign it window.Prism = PrismObject; additionalLanguages.forEach((lang) => { - require(`prismjs/components/prism-${lang}`); // eslint-disable-line + // eslint-disable-next-line global-require, import/no-dynamic-require + require(`prismjs/components/prism-${lang}`); }); delete (window as Window & {Prism?: typeof PrismNamespace}).Prism;