Skip to content

fix(resolve): don't let a user resolve.extensions override shadow framework-internal entries - #3226

Open
AhmedElBanna80 wants to merge 1 commit into
cloudflare:mainfrom
AhmedElBanna80:fix/resolve-extensions-framework-internal
Open

fix(resolve): don't let a user resolve.extensions override shadow framework-internal entries#3226
AhmedElBanna80 wants to merge 1 commit into
cloudflare:mainfrom
AhmedElBanna80:fix/resolve-extensions-framework-internal

Conversation

@AhmedElBanna80

Copy link
Copy Markdown

Problem

A webpack resolve.extensions / Turbopack resolveExtensions override replaces vinext's resolver defaults — normalizeViteResolveExtensions returned only the user's list. But the same resolver also resolves vinext's own internal, extensionless entry nitro/dist/presets/bun/runtime/bun (a .mjs file), so a user list that omits .mjs makes that entry unresolvable and the build dies with:

[UNRESOLVED_ENTRY] nitro/dist/presets/bun/runtime/bun

Reproduced by the official Next.js e2e fixture test/e2e/app-dir/resolve-extensions.

Fix

Append a small set of framework-required extensions (.mjs/.js/.mts/.cjs/.cts) at the lowest precedence, after the user's list. User extensions keep highest precedence for their own app code; the framework-internal entries stay resolvable. This mirrors what buildViteResolveExtensions already does for the default path (appending .cjs/.cts).

packages/vinext/src/routing/file-matcher.ts — one function, normalizeViteResolveExtensions.

Test

tests/file-matcher.test.ts:

  • a user override omitting .mjs still yields .mjs/.js, at lowest precedence (user extensions retain index 0);
  • an already-listed internal extension is not duplicated.

Mutation-proved: removing the append loop reds the first test. Existing resolve-extensions behaviour is unchanged — the current e2e fixture prepends a custom extension with the defaults already present, so appending is a no-op there; only the "user dropped .mjs" case changes, which is the bug.

…mework-internal entries

A webpack `resolve.extensions` / Turbopack `resolveExtensions` override replaces
vinext's resolver defaults (`normalizeViteResolveExtensions` returned only the
user's list). The same resolver also resolves vinext's own internal, extensionless
entry `nitro/dist/presets/bun/runtime/bun` — a `.mjs` file — so a user list that
omits `.mjs` makes that entry unresolvable and the build dies with
`[UNRESOLVED_ENTRY] nitro/dist/presets/bun/runtime/bun`.

Append a small set of framework-required extensions (`.mjs`/`.js`/`.mts`/`.cjs`/`.cts`)
at the LOWEST precedence after the user's list. User extensions keep highest
precedence for their app code; the internal entries stay resolvable. This mirrors
what `buildViteResolveExtensions` already does for the default path.

Fixes the `app-dir/resolve-extensions` case from the Next.js e2e suite.

Test: tests/file-matcher.test.ts — a user override omitting `.mjs` still yields
`.mjs`/`.js` (at lowest precedence), and an already-listed internal extension is
not duplicated.
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.

2 participants