Skip to content

Commit 88ee63a

Browse files
authored
Remove MDX processor on buildEnd (#10770)
1 parent 174ce25 commit 88ee63a

5 files changed

Lines changed: 50 additions & 2 deletions

File tree

.changeset/orange-ladybugs-nail.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@astrojs/mdx": patch
3+
---
4+
5+
Removes internal MDX processor on `buildEnd` to free up memory

benchmark/make-project/memory-default.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,17 @@ ${loremIpsum}
3535
);
3636
}
3737

38+
for (let i = 0; i < 100; i++) {
39+
const content = `\
40+
# Post ${i}
41+
42+
${loremIpsum}
43+
`;
44+
promises.push(
45+
fs.writeFile(new URL(`./src/content/blog/post-${i}.mdx`, projectDir), content, 'utf-8')
46+
);
47+
}
48+
3849
await fs.writeFile(
3950
new URL(`./src/pages/blog/[...slug].astro`, projectDir),
4051
`\
@@ -56,4 +67,16 @@ const { Content } = await entry.render();
5667
);
5768

5869
await Promise.all(promises);
70+
71+
await fs.writeFile(
72+
new URL('./astro.config.js', projectDir),
73+
`\
74+
import { defineConfig } from 'astro/config';
75+
import mdx from '@astrojs/mdx';
76+
77+
export default defineConfig({
78+
integrations: [mdx()],
79+
});`,
80+
'utf-8'
81+
);
5982
}

packages/astro/src/vite-plugin-markdown/index.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,15 @@ export default function markdown({ settings, logger }: AstroPluginOptions): Plug
5555

5656
const fileURL = pathToFileURL(fileId);
5757

58-
const renderResult = await processor!
58+
// `processor` is initialized in `buildStart`, and removed in `buildEnd`. `load`
59+
// should be called in between those two lifecycles, so this error should never happen
60+
if (!processor) {
61+
return this.error(
62+
'MDX processor is not initialized. This is an internal error. Please file an issue.'
63+
);
64+
}
65+
66+
const renderResult = await processor
5967
.render(raw.content, {
6068
// @ts-expect-error passing internal prop
6169
fileURL,

packages/integrations/mdx/src/index.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,17 @@ export default function mdx(partialMdxOptions: Partial<MdxOptions> = {}): AstroI
7575
),
7676
});
7777

78-
let processor: ReturnType<typeof createMdxProcessor>;
78+
let processor: ReturnType<typeof createMdxProcessor> | undefined;
7979

8080
updateConfig({
8181
vite: {
8282
plugins: [
8383
{
8484
name: '@mdx-js/rollup',
8585
enforce: 'pre',
86+
buildEnd() {
87+
processor = undefined;
88+
},
8689
configResolved(resolved) {
8790
processor = createMdxProcessor(mdxOptions, {
8891
sourcemap: !!resolved.build.sourcemap,
@@ -118,6 +121,14 @@ export default function mdx(partialMdxOptions: Partial<MdxOptions> = {}): AstroI
118121
// Ensure `data.astro` is available to all remark plugins
119122
setVfileFrontmatter(vfile, frontmatter);
120123

124+
// `processor` is initialized in `configResolved`, and removed in `buildEnd`. `transform`
125+
// should be called in between those two lifecycle, so this error should never happen
126+
if (!processor) {
127+
return this.error(
128+
'MDX processor is not initialized. This is an internal error. Please file an issue.'
129+
);
130+
}
131+
121132
try {
122133
const compiled = await processor.process(vfile);
123134

packages/markdown/remark/src/highlight.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ export async function highlightCodeBlocks(tree: Root, highlighter: Highlighter)
7373
for (const { node, language, grandParent, parent } of nodes) {
7474
const meta = (node.data as any)?.meta ?? node.properties.metastring ?? undefined;
7575
const code = toText(node, { whitespace: 'pre' });
76+
// TODO: In Astro 5, have `highlighter()` return hast directly to skip expensive HTML parsing and serialization.
7677
const html = await highlighter(code, language, { meta });
7778
// The replacement returns a root node with 1 child, the `<pr>` element replacement.
7879
const replacement = fromHtml(html, { fragment: true }).children[0] as Element;

0 commit comments

Comments
 (0)