fix(nuxt): restore the declared Nuxt >=3.7 floor for the Nitro 2 adapter - #4545
Draft
cat-ph wants to merge 5 commits into
Draft
fix(nuxt): restore the declared Nuxt >=3.7 floor for the Nitro 2 adapter#4545cat-ph wants to merge 5 commits into
cat-ph wants to merge 5 commits into
Conversation
Codex review flagged that importing useRuntimeConfig from '#imports' breaks apps that set nitro.imports: false. Nitro only registers that virtual module when auto-imports are enabled, and no single import specifier spans both old nitropack (<2.9.5, no bare './runtime' export; deep './runtime/*' files get externalized and crash on '#internal/nitro/virtual/*') and that config. So select at build time instead: Nuxt >=3.12 (nitropack >=2.9.6 guaranteed) keeps the explicit nitropack/runtime adapter, older Nuxt gets a legacy adapter on '#imports' — the mechanism this module shipped with pre-split.
Nuxt 3.11.2 already requires nitropack ^2.9.6, so it can use the nitropack/runtime adapter and keep nitro.imports: false working; only older versions fall back to the legacy #imports adapter.
Codex review round 3: a Nuxt-version cutoff misroutes installs whose lockfile floats or pins nitropack across the 2.9.5 boundary. Probe the './runtime' entry in the export map of the nitropack copy Nuxt resolves (via createRequire from appDir) and route on capability instead; fall back to the legacy adapter when no manifest is resolvable.
Codex review round 4: Nuxt >= 4.5 depends on nitropack via @nuxt/nitro-server, so under isolated pnpm installs the manifest is not resolvable from the nuxt package and the probe would misroute modern Nuxt to the legacy adapter (breaking nitro.imports: false there). Treat an unresolvable manifest as inconclusive and gate on Nuxt >= 3.11.2 — the first release whose nitropack range guarantees the bare './runtime' export — instead of assuming legacy.
Contributor
Contributor
|
Size Change: +1.17 kB (+0.01%) Total Size: 19.7 MB 📦 View Changed
ℹ️ View Unchanged
|
Contributor
|
This PR hasn't seen activity in a week! Should it be merged, closed, or further worked on? If you want to keep it open, post a comment or remove the |
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.
Problem
The Nitro 2 adapter added in #4445 imports
defineNitroPluginanduseRuntimeConfigfrom the barenitropack/runtimesubpath. That subpath only exists in nitropack >= 2.9.5, but the module declares anuxt: '>=3.7.0'compatibility floor, and Nuxt 3.7–3.11 resolve nitropack ranges that can sit below it (3.7 ->^2.6.1, 3.8–3.10 ->^2.8.x, 3.11 ->^2.9.4).On those versions the app builds with unresolved-import warnings and the packed server crashes at startup:
Could not resolve import "nitropack/runtime" ... treating it as an external dependency(x5 duringnuxt build)Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './runtime' is not defined by "exports" in .../nitropack/package.jsonwhen runningnode .output/server/index.mjsReproduced against a minimal app pinned to
nuxt@3.7.0+nitropack@2.6.2.Changes
No single import specifier works across the whole supported range, so the module now picks between three adapters at build time (extending the existing v2/v3 selection). Rather than keying off Nuxt versions, it probes the export map of the nitropack copy Nuxt itself resolves — so lockfiles that float or pin nitropack still get the right adapter:
nitro-plugin-v3nitro/nitro/runtime-config(unchanged)./runtime(>= 2.9.5)nitro-plugin-v2nitropack/runtime(unchanged)nitro-plugin-v2-legacy(new)#importsvirtual moduleWhen the probe is inconclusive (no nitropack manifest resolvable from the nuxt package — e.g. Nuxt >= 4.5 depends on nitropack via
@nuxt/nitro-server, unreachable under isolated installs), the module falls back to a Nuxt-version gate: >= 3.11.2 is the first release whose nitropack range guarantees the bare./runtimeexport.Why the legacy adapter uses
#imports: it's the only mechanism old Nitro 2 supports — and it's exactly what this module shipped with before the adapter split, so old-nitropack installs get the code path that already worked for them. The alternatives fail: barenitropack/runtimedoesn't exist below 2.9.5, and deep subpaths likenitropack/runtime/configresolve at build time but old Nitro externalizes them into.output/server/node_modules, where they crash on Nitro's build-time-only#internal/nitro/virtual/*specifiers.Why modern Nuxt keeps the explicit import instead of
#importseverywhere: Nitro only registers the#importsvirtual module when auto-imports are enabled, so#importsbreaks apps that setnitro: { imports: false }(caught by Codex review of an earlier iteration of this fix).Tests: the adapter-source assertions in
nitro-plugin.test.mjsnow cover the legacy adapter and forbid the floor-breaking import there; the registration matrix insourcemaps-ssr.test.mjscovers the new routing (old nitropack exports -> legacy, new exports -> v2 even on Nuxt 3.7, unresolvable manifest -> version fallback on both sides of 3.11.2, Nuxt 5 -> v3).Verified by installing the rebuilt package into real apps:
nitro: { imports: false }Known remaining edge (not a regression): nitropack < 2.9.5 combined with
nitro: { imports: false }doesn't work, same as every released version of this module.Follow-up (separate PR): a pinned-floor consumer fixture mirroring
nuxt5-consumer.test.mjsso the floor is exercised in CI.Release info Sub-libraries affected
Libraries affected
Checklist
If releasing new changes
pnpm changesetto generate a changeset file🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Claude Code (Fable 5) investigated the reported floor break, bisected the nitropack export map across published versions to find where the bare
./runtimesubpath appeared (2.9.5), and reproduced the crash in a pinned nuxt 3.7.0 + nitropack 2.6.2 app. Two earlier single-adapter fixes were tried and rejected against real fixtures:#importseverywhere (Codex review via autoreview caught thenitro: { imports: false }regression, confirmed empirically) and deepnitropack/runtime/configsubpaths (resolve everywhere but old Nitro externalizes them and crashes on internal virtual specifiers). The build-time three-way adapter selection was the only shape that passed every fixture; a Nuxt-version cutoff for it was refined across two further review rounds into an export-map probe of the resolved nitropack (version routing misclassifies floated/pinned lockfiles) with a version-gate fallback (the probe is blind on Nuxt >= 4.5 isolated installs, where nitropack sits under @nuxt/nitro-server). Codex review ran as the closeout gate.