Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 38 additions & 26 deletions packages/nuxi/src/commands/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,37 +37,49 @@ const command = defineCommand({

const cwd = resolve(ctx.args.cwd || ctx.args.rootDir)

const { loadNuxt } = await loadKit(cwd)
const defaultOutput = resolve(cwd, '.output', 'nitro.json')

const resolvedOutputDir = await new Promise<string>((res) => {
loadNuxt({
cwd,
dotenv: {
cwd,
fileName: ctx.args.dotenv,
},
envName: ctx.args.envName, // c12 will fall back to NODE_ENV
ready: true,
overrides: {
...(ctx.args.extends && { extends: ctx.args.extends }),
modules: [
function (_, nuxt) {
nuxt.hook('nitro:init', (nitro) => {
res(resolve(nuxt.options.srcDir || cwd, nitro.options.output.dir || '.output', 'nitro.json'))
})
},
],
},
}).then(nuxt => nuxt.close()).catch(() => '')
})
let nitroJSONPath: string | undefined

const defaultOutput = resolve(cwd, '.output', 'nitro.json') // for backwards compatibility
// Try the default output path first to avoid loading Nuxt (which runs
// module setup and may emit warnings about missing env vars that are
// already baked into the build output).
if (existsSync(defaultOutput)) {
nitroJSONPath = defaultOutput
}
Comment on lines +47 to +49
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Preserve --extends on the .output fast path.

Line 47 short-circuits before the explicit override on Line 63 is ever applied. If cwd already has a .output/nitro.json, nuxi preview --extends ... can boot that artifact instead of the layered build the caller asked for.

💡 One minimal way to keep the optimization for the common case
-    if (existsSync(defaultOutput)) {
+    if (existsSync(defaultOutput) && !ctx.args.extends) {
       nitroJSONPath = defaultOutput
     }
     else {
       const { loadNuxt } = await loadKit(cwd)
@@
       })
 
-      if (resolvedOutputDir && existsSync(resolvedOutputDir)) {
+      if (resolvedOutputDir && existsSync(resolvedOutputDir)) {
         nitroJSONPath = resolvedOutputDir
       }
+      else if (existsSync(defaultOutput)) {
+        nitroJSONPath = defaultOutput
+      }
     }

Also applies to: 63-64

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/nuxi/src/commands/preview.ts` around lines 47 - 49, The fast-path
that sets nitroJSONPath when existsSync(defaultOutput) should not short-circuit
when the CLI `--extends` option is present; modify the logic around
existsSync(defaultOutput) and the later override (the code setting nitroJSONPath
on the explicit override path) so that if an extends value is provided (the
parsed option used by preview, e.g., the `--extends` flag variable), you skip
the short-circuit and allow the explicit nitroJSONPath override to take effect.
In practice, check the parsed extends option (the same variable used later in
the preview command) before assigning nitroJSONPath from defaultOutput and apply
the same conditional to the later 63-64 fast-path to preserve the layered build
when `--extends` is passed.

else {
const { loadNuxt } = await loadKit(cwd)

const resolvedOutputDir = await new Promise<string>((res) => {
loadNuxt({
cwd,
dotenv: {
cwd,
fileName: ctx.args.dotenv,
},
envName: ctx.args.envName, // c12 will fall back to NODE_ENV
ready: true,
overrides: {
...(ctx.args.extends && { extends: ctx.args.extends }),
modules: [
function (_, nuxt) {
nuxt.hook('nitro:init', (nitro) => {
res(resolve(nuxt.options.srcDir || cwd, nitro.options.output.dir || '.output', 'nitro.json'))
})
},
],
},
}).then(nuxt => nuxt.close()).catch(() => '')
})

if (resolvedOutputDir && existsSync(resolvedOutputDir)) {
nitroJSONPath = resolvedOutputDir
}
}

const nitroJSONPaths = [resolvedOutputDir, defaultOutput].filter(Boolean)
const nitroJSONPath = nitroJSONPaths.find(p => existsSync(p))
if (!nitroJSONPath) {
logger.error(
`Cannot find ${colors.cyan('nitro.json')}. Did you run ${colors.cyan('nuxi build')} first? Search path:\n${nitroJSONPaths.join('\n')}`,
`Cannot find ${colors.cyan('nitro.json')}. Did you run ${colors.cyan('nuxi build')} first? Search path:\n${defaultOutput}`,
)
Comment on lines 80 to 83
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Report the path that was actually checked.

Once the fallback runs, a miss may come from a non-default nitro.json location, but this error still prints only defaultOutput. That makes the failure harder to debug because the reported search path no longer matches the lookup logic.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/nuxi/src/commands/preview.ts` around lines 80 - 83, The error
message logged when nitroJSONPath is not found should include the actual path(s)
that were checked (the value of nitroJSONPath or its resolved lookup) in
addition to the defaultOutput; update the logger.error call in preview.ts (the
block referencing nitroJSONPath, defaultOutput and colors.cyan('nitro.json')) to
interpolate or append the real checked path(s) (nitroJSONPath or its resolved
candidate) so the message shows both the searched defaultOutput and the actual
path(s) attempted, keeping the existing descriptive text about running
colors.cyan('nuxi build').

process.exit(1)
}
Expand Down
Loading