Minimal reproduction for a bug where a CJS-only dependency, reached only through a Nuxt layer's plugin/layout (a real installed package, not a local project file), is served raw by Vite's dev server instead of being pre-bundled — breaking with:
The requested module '.../extend/index.js' does not provide an export named 'default'
Related upstream issues:
- nuxt/nuxt#31015
- nuxt-content/mdc#468 (a real-world instance of the same bug, via
@nuxtjs/mdc→unified→extend)
- The Nuxt app itself (
app/,nuxt.config.ts), which extendsbroken-cjs-layerviaextends. broken-cjs-layer/— a tiny Nuxt layer, installed as a real package viafile:(this matters — see "What we found" below), with a client plugin (app/plugins/broken.client.mjs) and a default layout (app/layouts/default.vue), both of which importunified, which itself doesimport extend from 'extend'(a CJS-only package).
pnpm install
pnpm devOpen the dev server. In the terminal and/or browser console:
SyntaxError: The requested module '.../extend/index.js' does not provide an export named 'default'
WARN [NUXT_B7002] Some vite.optimizeDeps.include entries could not be resolved: extend.
Note the second line: nuxt.config.ts already has vite.optimizeDeps.include: ['extend'] set (the documented workaround for this class of bug), and Nuxt itself reports that entry as unresolvable. The dependency is never optimized, so the browser gets served the raw CJS file directly and fails on the default import.
- The failure requires the layer to be a real installed package (resolved
via
file:here) — pointingextendsat an equivalent local layer directory that isn't installed via a package manager does not reproduce it; Vite's dependency scanner discovers the sameunified→extendchain fine in that case. - We also confirmed this reproduces identically whether the broken import is
reached through a Nuxt module's registered plugin (
defineNuxtModuleaddPlugin/addComponent) or, as here, through a Nuxt layer (extends) — the underlying bug is the same regardless of which registration mechanism surfaces it.
- A
vite.ssrconfig block is not required to reproduce this (we initially thought it was implicated viaEnvironmentsPlugin'sconfigEnvironmenterasingoptimizeDeps.includefor the client environment — removing it made no difference here, so that appears to be a separate, additional issue rather than the root cause of this one). - In this minimal repro, the error is logged to the console but the page
still renders — it doesn't reproduce the full blank-page severity we saw
in the production app that motivated this report. In that app, the same
underlying error was thrown while loading the default layout, and Nuxt's
own
LayoutLoaderescalated it to a fatal app-level error (H3Error→showError()→<NuxtRoot><Error>), replacing the entire page. We haven't yet pinned down what additional condition is needed for this minimal repro'sLayoutLoaderto hit that same escalation path, so take the severity as "confirmed fatal in a real app, cosmetic-only so far in this toy repro" rather than assuming they're equivalent.
nuxt: 4.5.2
vite: 8.2.2 (Rolldown-based dep optimizer)
vue: 3.5.41 (via nuxt)
node: 22
pnpm: 10.x