Skip to content

fix(transforms): compile MDX before parsing its imports (depends on #2999) - #3009

Merged
kwakayama merged 1 commit into
mainfrom
fix/tsx-imports-mdx
Jul 22, 2026
Merged

fix(transforms): compile MDX before parsing its imports (depends on #2999)#3009
kwakayama merged 1 commit into
mainfrom
fix/tsx-imports-mdx

Conversation

@mattboon

Copy link
Copy Markdown
Collaborator

Summary

A .tsx page importing an .mdx component 500'd with a message that sent you looking for a file that was sitting right there:

Component has missing dependencies:
  - @/components/snippet.mdx (from …/pages/test/r-tsx-imports-mdx.tsx):
    Failed to read file: Transform failed with 1 error: <stdin>:1:1: ERROR: Syntax error

The file was found and read. The dependency scan of it failed. parseLocalImports hands source to esbuild to strip types before lexing imports, choosing the loader from the file extension — and .mdx maps to the jsx loader. Markdown prose is not JSX, so esbuild rejected byte one, and the resulting exception was reported as a missing dependency.

That also explains the asymmetry the reproducer noticed — MDX importing MDX works fine, because MDX pages are compiled through the parse stage first; only this dependency-scanning path skipped it.

MDX and Markdown are now compiled to JSX first, exactly as the transform pipeline's parse stage does, and the imports are read out of that. .css and .json already short-circuited above this point; .mdx simply had no equivalent handling.

Reproduction

  • Route: r-tsx-imports-mdx.tsx
  • Test: src/transforms/esm/import-parser.test.ts (new — this module had no direct coverage)

Test evidence

parses imports from a .tsx file ... ok
parses imports out of an .mdx file instead of failing to lex it ... ok
handles an .mdx file with no imports ... ok
short-circuits .css and .json without invoking the compiler ... ok
ok | 1 passed (4 steps) | 0 failed

The MDX cases register a stub ContentProcessor (the MDX extension is not loaded in unit tests) and assert both that the imports are found and that the content compiler was invoked — so the routing of .mdx away from raw esbuild is what is actually under test.

Wider suite: deno task test:unit2525 passed | 0 failed.

SSR evidence

$ curl -so/dev/null -w '%{http_code}' http://localhost:3010/test/r-tsx-imports-mdx
200          # was 500

$ curl -s http://localhost:3010/test/r-tsx-imports-mdx | grep -oE 'Snippet</h2>|piece of MDX|point one'
Snippet</h2>
piece of MDX
point one

The MDX renders inline, which is what the route was written to check.

Client evidence

PASS /test/r-tsx-imports-mdx

All six MDX routes in the matrix (n, o, p, q, r, s) now pass the hydration sweep.

Related

  • Bug 7 of the reproducer matrix.

Chain: this PR is part of a 13-PR chain fixing the bugs catalogued in
veryfront-router-testing.
Its base is the previous PR in the chain, so the diff shows only this fix.
The root of the chain is #2999 (fix/ssr-lazy-import-graceful-degrade) — merge #2999 first, then
rebase the chain onto main.

Regression gate: deno task test:unit2525 passed | 0 failed; deno task lint,
deno task fmt:check and deno task typecheck all clean. The reproducer's full 56-route
matrix (ROUTES.txt + sweep.sh) was re-run after every fix: 7 routes improved, 0 regressed.
A 46-route Chromium hydration sweep (client-sweep.mjs) backs the client-side claims.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6df7b936f3

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +65 to +67
"server",
);
parseSource = compiled.compiledCode;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Handle server-rewritten MDX imports

When an MDX file imports a project file with a relative specifier, the real content compiler invoked here with the server target rewrites ./Child or ../Child to a file://... specifier before parseSource is lexed. The loop below only records ./, ../, and @/ imports, so those relative MDX dependencies no longer enter parseResult.imports; SSRModuleLoader then skips the recursive transform and cannot rewrite them to cache temp modules, leaving the compiled MDX to import raw project files or miss dependency errors. Please preserve the original specifiers for dependency parsing or normalize file:// imports back to local project paths.

Useful? React with 👍 / 👎.

@mattboon
mattboon force-pushed the fix/custom-error-page-in-dev branch from 016c9ae to 8b8ce7e Compare July 21, 2026 18:19
@mattboon
mattboon force-pushed the fix/tsx-imports-mdx branch from 6df7b93 to b6d4ac1 Compare July 21, 2026 18:19

@kwakayama kwakayama left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Score: 86/100

Compiling MDX/Markdown before dependency scanning matches the main transform pipeline and fixes the raw-MDX-to-esbuild failure. The targeted tests cover MDX with imports, MDX without imports, TSX, and CSS/JSON short-circuits.

Not merge-ready yet:

  • This is stacked on lower open PRs, including blocked/type-failing PRs.
  • The PR status rollup only shows CLA, not full CI.

Watch item: import discovery now depends on the full MDX content compiler in this utility path. That is probably the right semantic match, but it increases coupling and runtime cost, so it should remain intentional.

@mattboon
mattboon force-pushed the fix/custom-error-page-in-dev branch from 8b8ce7e to 69e526f Compare July 21, 2026 19:22
@mattboon
mattboon force-pushed the fix/tsx-imports-mdx branch from b6d4ac1 to 4566899 Compare July 21, 2026 19:22
@mattboon
mattboon force-pushed the fix/custom-error-page-in-dev branch from 69e526f to 7506907 Compare July 21, 2026 19:44
@mattboon
mattboon force-pushed the fix/tsx-imports-mdx branch from 4566899 to 7d862f1 Compare July 21, 2026 19:44
@kwakayama
kwakayama force-pushed the fix/tsx-imports-mdx branch from 7d862f1 to 0d6621f Compare July 21, 2026 20:30
@kwakayama
kwakayama force-pushed the fix/custom-error-page-in-dev branch 2 times, most recently from 00674af to d3848ba Compare July 21, 2026 20:38
@kwakayama
kwakayama force-pushed the fix/tsx-imports-mdx branch from 0d6621f to 1c906fa Compare July 21, 2026 20:38
kwakayama
kwakayama previously approved these changes Jul 21, 2026

@kwakayama kwakayama left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up approval after #2999 merged and the stack was rebased onto main.

Score: 91/100.

Rationale: MDX import compilation ordering is scoped and covered by the rebased stack regression pass.

Next step: merge after lower stack PRs and refreshed checks are green.

@kwakayama
kwakayama force-pushed the fix/custom-error-page-in-dev branch from eed4452 to 6a0d2f6 Compare July 21, 2026 22:39
@kwakayama
kwakayama force-pushed the fix/tsx-imports-mdx branch 2 times, most recently from 4a473a3 to ee402cc Compare July 21, 2026 22:47
@kwakayama
kwakayama force-pushed the fix/custom-error-page-in-dev branch from 6a0d2f6 to 82c90c5 Compare July 21, 2026 22:47
@kwakayama
kwakayama force-pushed the fix/tsx-imports-mdx branch from ee402cc to edcb779 Compare July 21, 2026 22:57
@kwakayama
kwakayama force-pushed the fix/custom-error-page-in-dev branch from 82c90c5 to 96c3a4d Compare July 21, 2026 22:57
@kwakayama
kwakayama force-pushed the fix/tsx-imports-mdx branch from edcb779 to d054352 Compare July 21, 2026 23:38
@kwakayama
kwakayama force-pushed the fix/custom-error-page-in-dev branch 2 times, most recently from 27ac9dd to e42febe Compare July 21, 2026 23:44
@kwakayama
kwakayama force-pushed the fix/tsx-imports-mdx branch 2 times, most recently from 7f53c76 to 94cb29b Compare July 21, 2026 23:53
@kwakayama
kwakayama force-pushed the fix/custom-error-page-in-dev branch 2 times, most recently from 59203c4 to 2b05d70 Compare July 22, 2026 00:15
@kwakayama
kwakayama force-pushed the fix/tsx-imports-mdx branch from 94cb29b to 36d7973 Compare July 22, 2026 00:15
@kwakayama
kwakayama force-pushed the fix/custom-error-page-in-dev branch from 2b05d70 to 1649f59 Compare July 22, 2026 00:22
@kwakayama
kwakayama force-pushed the fix/tsx-imports-mdx branch from 36d7973 to 17b4f24 Compare July 22, 2026 00:22
@kwakayama
kwakayama force-pushed the fix/custom-error-page-in-dev branch from 1649f59 to cd3180c Compare July 22, 2026 00:29
@kwakayama
kwakayama force-pushed the fix/tsx-imports-mdx branch from 17b4f24 to 7a3df0c Compare July 22, 2026 00:29
@kwakayama
kwakayama force-pushed the fix/custom-error-page-in-dev branch from cd3180c to a70330e Compare July 22, 2026 00:43
@kwakayama
kwakayama force-pushed the fix/tsx-imports-mdx branch from 7a3df0c to daf8bbb Compare July 22, 2026 00:43
@kwakayama
kwakayama force-pushed the fix/custom-error-page-in-dev branch from a70330e to 7cecf2d Compare July 22, 2026 00:47
@kwakayama
kwakayama force-pushed the fix/tsx-imports-mdx branch 2 times, most recently from 4df9e0e to 57e5df1 Compare July 22, 2026 00:54
@kwakayama
kwakayama force-pushed the fix/custom-error-page-in-dev branch from 7cecf2d to 2b79b86 Compare July 22, 2026 00:54
Base automatically changed from fix/custom-error-page-in-dev to main July 22, 2026 01:03
@kwakayama
kwakayama dismissed their stale review July 22, 2026 01:03

The base branch was changed.

MDX source is not JSX, so parsing raw .mdx through the JSX loader reported existing dependencies as missing and dropped server-rewritten file:// imports.

Constraint: Unit tests should keep Deno leak checks enabled and close the shared esbuild service instead of adding sanitizer opt-outs.

Rejected: Parsing raw MDX as JSX | it fails before import analysis can see the compiled module imports.

Confidence: high

Scope-risk: moderate

Directive: Keep MDX import analysis aligned with the content compiler target that rewrites imports for SSR.

Tested: deno test --allow-all src/transforms/esm/import-parser.test.ts

Tested: deno task lint:sanitizer-baseline

Tested: deno task lint

Not-tested: full repository CI locally
@kwakayama
kwakayama force-pushed the fix/tsx-imports-mdx branch from 57e5df1 to 9923c98 Compare July 22, 2026 01:04

@kwakayama kwakayama left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approval after rebasing onto current main and removing sanitizer opt-outs from the import-parser regression test.

Score: 92/100.

Real bug: raw .mdx is not JSX, so parsing it directly through the JSX/esbuild path can fail before dependency analysis sees the imports. The fix compiles MDX first and then parses the compiled module, including server-rewritten file:// imports for relative components and CSS.

Quality note: the test now keeps Deno leak checks enabled and stops the shared esbuild service instead of raising the sanitizer baseline.

Verification:

  • deno test --allow-all src/transforms/esm/import-parser.test.ts
  • deno task lint:sanitizer-baseline
  • deno task lint
  • deno test --allow-all src/transforms/esm/import-parser.test.ts src/transforms/esm/specifier-resolver.test.ts src/rendering/orchestrator/module-loader/esm-rewriter.test.ts

Next step: wait for refreshed GitHub checks, then merge when green.

@kwakayama
kwakayama enabled auto-merge (squash) July 22, 2026 01:04
@kwakayama
kwakayama merged commit 213b12c into main Jul 22, 2026
28 checks passed
@kwakayama
kwakayama deleted the fix/tsx-imports-mdx branch July 22, 2026 01:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants