perf(web): re-enable Turbopack dev — drop dead MDX JS plugin chain#1780
Merged
Conversation
`next dev --turbopack` is 10–50× faster than the Webpack default for HMR + per-route first-compile. PR #1667 disabled it because the inline remark `containerDirective` plugin in `next.config.ts` was a closure that Turbopack's worker pool cannot serialize. Empirically the entire JS plugin chain has the same problem — even after the inline closure is hoisted to its own module, `next dev --turbopack` still aborts with Error: loader /node_modules/@next/mdx/mdx-js-loader.js for match "#next-mdx" does not have serializable options. The trade-off here is unusual: this plugin chain is **dead code at compile time**. There are zero `.mdx` pages in `web/src/**` (verified via `find` + `grep`). All runtime markdown rendering happens through `web/src/components/markdown.tsx`, which keeps its own React-side `react-markdown` pipeline (gfm, highlight, directives, frontmatter, headerId) — that path is untouched. So: drop the JS plugin chain from `createMDXPlugin`. The `withNextMDX` wrapper is kept (so `mdx-components.tsx` stays wired) and `pageExtensions` keeps `'mdx'` (so the route resolver still recognises the extension). When `.mdx` pages are actually introduced, the recommended path is `experimental.mdxRs: true` (Rust-based, Turbopack- compatible) — see updated comment in `next.config.ts` for context. Re-enable the flag in `web/package.json:dev`. Local verification: `./node_modules/.bin/next dev --turbopack` reaches "Ready" in 1.5 s with zero loader-serialization errors; `yarn tsc --noEmit` reports zero errors. §K.12 invariant cross-check ============================ Largely n/a (frontend dev tooling). Direct hit: - #12 (grep-zero LightRAG) — `rg -i lightrag web/src/` returns zero hits both before and after. 4-pattern pre-check matrix ========================== - Pattern 1 v1 (`.mdx` page consumers): `find web/src -name '*.mdx'` returns zero. `rg "from '[^']*\\.mdx'" web/src` returns zero. Confirms the JS plugin chain has no live consumers. - Pattern 1 v2 (runtime markdown plugin chain): unchanged in `components/markdown.tsx`. Removing JS plugins from `next.config.ts` does not affect document rendering — react-markdown imports its own copy of remarkGfm / rehypeHighlight / etc. directly. - Pattern 2 (response-shape change list): n/a, this PR does not touch any backend or generated schema. - Pattern 3 (additive helpers): n/a, dev-tooling only. simple-stable directive 4-guardrail =================================== - #1 不无限扩范围 — 2 files / +16 / -55. Did not extract plugins to modules (would be future-only dead code given zero `.mdx` files); did not switch to `experimental.mdxRs` (kept current MDX setup empty-but-present so future adopters re-add plugins explicitly). - #2 尽快上线 — earayu2 directive: edit code → instant reload, no added manual burden. Turbopack ready in 1.5 s, HMR kicks in automatically; `dev` script still runs `yarn install && yarn i18n:sync` so engineers who pull dependency updates do not need any extra command. - #3 简单稳定 — fewer plugins is fewer moving parts. The runtime markdown path keeps the production-tested chain. - #4 私有化部署免维护 — operator-invisible; production builds unaffected (zero `.mdx` files means `next build` output is identical before/after). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
next dev --turbopackis 10–50× faster than the Webpack default for HMR + per-route first-compile. PR #1667 disabled it because the inlinecontainerDirectiveremark plugin innext.config.tswas a closure that Turbopack's worker pool cannot serialize. Empirically the entire JS plugin chain has the same problem — even after the inline closure is hoisted to its own module,next dev --turbopackstill aborts with:The unusual trade-off here: this plugin chain is dead code at compile time. There are zero
.mdxpages inweb/src/**(verified viafind+grep). All runtime markdown rendering happens throughweb/src/components/markdown.tsx, which keeps its own React-sidereact-markdownpipeline (gfm, highlight, directives, frontmatter, headerId) — that path is untouched.So: drop the JS plugin chain from
createMDXPlugin. ThewithNextMDXwrapper is kept (somdx-components.tsxstays wired) andpageExtensionskeeps'mdx'(so the route resolver still recognises the extension). When.mdxpages are actually introduced, the recommended path isexperimental.mdxRs: true(Rust-based, Turbopack-compatible) — comment innext.config.tsupdated.Re-enable the flag in
web/package.json:dev. Local verification:./node_modules/.bin/next dev --turbopackreaches "Ready" in 1.5 s with zero loader-serialization errors;yarn tsc --noEmitreports zero errors.§K.12 invariant cross-check
Largely n/a (frontend dev tooling). Direct hit:
rg -i lightrag web/src/returns zero hits both before and after ✅.4-pattern pre-check matrix
.mdxpage consumers): `find web/src -name '.mdx'` returns zero. `rg "from '[^']\.mdx'" web/src` returns zero. Confirms the JS plugin chain has no live consumers.components/markdown.tsx. Removing JS plugins fromnext.config.tsdoes not affect document rendering — react-markdown imports its own copies of remarkGfm / rehypeHighlight / etc. directly.simple-stable directive 4-guardrail
.mdxfiles); did not switch toexperimental.mdxRs(kept current MDX setup empty-but-present so future adopters re-add plugins explicitly).devscript still runsyarn install && yarn i18n:syncso engineers who pull dependency updates do not need any extra command..mdxfiles meansnext buildoutput is identical before/after).Test plan
next dev --turbopackreaches "Ready in 1477ms" cleanly (no loader-serialization error)yarn tsc --noEmit→ 0 errorsfind web/src -name '*.mdx'→ 0 files (confirms plugin chain was dead code)rg \"from '[^']*\\.mdx'\" web/src→ 0 imports (confirms no consumer)yarn dev+ verify HMR feels instant on edit (deferred to reviewer-side; my session has no live dev stack running)🤖 Generated with Claude Code