Describe the bug
With pack.shims: true and pack.unbundle: true, the generated CommonJS output (.cjs) contains bare ESM statements at the top of the file:
import "node:path";
import "node:url";
import.meta.url;
This is not valid CommonJS, so require()-ing the built .cjs throws at module load, before any code runs:
SyntaxError: Cannot use import statement outside a module
The shim preamble is emitted verbatim into both the .mjs and the .cjs. In the ESM output those statements are legal; in the CommonJS output they are not, and they are neither transformed to their CJS equivalents nor omitted. vp pack reports success (exit 0) and writes the broken artifact.
The trigger is the combination of the two flags. With shims: true and unbundle left at its default, import.meta.url / node: builtins are correctly compiled to their CJS forms (require("url").pathToFileURL(__filename).href, require("node:path")); it is only shims: true + unbundle: true together that leaks the raw ESM preamble.
Expected: the CommonJS build must be valid CommonJS — the shim preamble should be compiled to CJS-safe equivalents (or omitted) in the .cjs, exactly as it is when unbundle is off.
Reproduction
https://github.com/TheHolyWaffle/vite-plus-cjs-shim-leak
Steps to reproduce
npm install
npx vp pack
# build succeeds (exit 0)
# require the CommonJS output the way a CJS consumer would:
node -e "require('./dist/index.cjs')"
# -> SyntaxError: Cannot use import statement outside a module
# the ESM output is fine:
node --input-type=module -e "import('./dist/index.mjs').then(m => console.log(m.under('/tmp')))"
# -> /tmp/sub
Generated dist/index.cjs (note lines 1-3):
import "node:path";
import "node:url";
import.meta.url;
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
let node_path = require("node:path");
//#region src/index.ts
function under(dir) {
return (0, node_path.resolve)(dir, "sub");
}
//#endregion
exports.under = under;
Removing unbundle: true (keeping shims: true) produces valid CommonJS
(let node_path = require("node:path"), no leading import), which loads without error.
System Info
# `vp env current` is not a command in 0.2.3 (errors "Command 'env' not found"),
# so pasting `vp --version` (which includes the tool matrix) plus runtime versions:
$ npx vp --version
vp v0.2.3
Local vite-plus:
vite-plus v0.2.3
Tools:
vite v8.1.3
rolldown v1.1.4
vitest v4.1.9
oxfmt v0.57.0
oxlint v1.72.0
oxlint-tsgolint v0.24.0
tsdown v0.22.3
$ node --version
v24.16.0
$ npm --version
11.13.0
# OS: macOS (darwin 25.5.0)
Used Package Manager
npm
Logs
$ npx vp pack
ℹ entry: src/index.ts
ℹ Build start
ℹ [ESM] dist/index.mjs ...
✔ Build complete
ℹ [CJS] dist/index.cjs ...
✔ Build complete
# exit code: 0 — the invalid .cjs is written without any warning
$ node -e "require('./dist/index.cjs')"
.../dist/index.cjs:1
import "node:path";
^^^^^^
SyntaxError: Cannot use import statement outside a module
at wrapSafe (node:internal/modules/cjs/loader:1691:18)
at Module._compile (node:internal/modules/cjs/loader:1734:20)
...
Validations
Describe the bug
With
pack.shims: trueandpack.unbundle: true, the generated CommonJS output (.cjs) contains bare ESM statements at the top of the file:This is not valid CommonJS, so
require()-ing the built.cjsthrows at module load, before any code runs:The shim preamble is emitted verbatim into both the
.mjsand the.cjs. In the ESM output those statements are legal; in the CommonJS output they are not, and they are neither transformed to their CJS equivalents nor omitted.vp packreports success (exit 0) and writes the broken artifact.The trigger is the combination of the two flags. With
shims: trueandunbundleleft at its default,import.meta.url/node:builtins are correctly compiled to their CJS forms (require("url").pathToFileURL(__filename).href,require("node:path")); it is onlyshims: true+unbundle: truetogether that leaks the raw ESM preamble.Expected: the CommonJS build must be valid CommonJS — the shim preamble should be compiled to CJS-safe equivalents (or omitted) in the
.cjs, exactly as it is whenunbundleis off.Reproduction
https://github.com/TheHolyWaffle/vite-plus-cjs-shim-leak
Steps to reproduce
Generated
dist/index.cjs(note lines 1-3):Removing
unbundle: true(keepingshims: true) produces valid CommonJS(
let node_path = require("node:path"), no leadingimport), which loads without error.System Info
Used Package Manager
npm
Logs
Validations