Repository navigation
output.library.type: 'module' defaults output.module to false, emitting invalid JavaScript (export inside IIFE) #22061
Description
Have you used AI?
Yes
Which part of webpack is affected?
config (options, defaults, validation)
Bug Description
Following #22011 / commit c4cd6ca4 which removed the experiments.outputModule experiment flag, ESM output options (output.module, library types "module" / "modern-module", etc.) became first-class configurations.
However, in lib/config/defaults.js:1645, output.module defaults to true only for universal, deno, or bun targets:
F(output, "module", () =>
Boolean(
tp &&
((tp.node === null && tp.web === null && tp.module !== false) ||
tp.deno === true ||
tp.bun === true)
)
);When building an ESM library (e.g. for web or node) by configuring:
module.exports = {
output: {
library: {
type: "module"
}
}
};(or on an entry via entry[name].library.type: "module"):
output.moduleremainsfalseby default.output.iiferemainstrueby default for non-module output.ModuleLibraryPluginemits anexport default ...orexport { ... }statement.- Because
output.moduleisfalse, the bundle is wrapped in an IIFE:
(() => {
// ...
let __webpack_exports__ = __webpack_require__("./index.js");
export default __webpack_exports__;
})();- In production mode, minification fails with:
"Export" statement may only appear at the top level [bundle.js:45,undefined](Terser syntax error). - In development mode (or without minifier), runtime execution fails with:
SyntaxError: Unexpected token 'export'.
Additionally, if a user explicitly sets output: { module: false, library: { type: "module" } }, webpack emits this invalid JavaScript syntax without any validation or error, whereas previously it threw:
library type "module" is only allowed when 'experiments.outputModule' is enabled.
Link to Minimal Reproduction and steps to reproduce
Minimal reproduction script:
const webpack = require("webpack");
const vm = require("vm");
const fs = require("fs");
const path = require("path");
const outDir = path.resolve("./dist-repro");
webpack({
mode: "development",
entry: "./test/fixtures/a.js",
output: {
path: outDir,
filename: "bundle.js",
library: {
type: "module"
}
}
}, (err, stats) => {
if (err) throw err;
const code = fs.readFileSync(path.join(outDir, "bundle.js"), "utf8");
try {
new vm.Script(code);
console.log("Syntax is valid!");
} catch (e) {
console.error("Syntax Error in emitted bundle:", e.message);
}
fs.rmSync(outDir, { recursive: true, force: true });
});Steps:
- Run the script above on webpack
main. - Output displays
Syntax Error in emitted bundle: Unexpected token 'export'. - Switch mode to
"production"and see Terser throw:"Export" statement may only appear at the top level.
Expected Behavior
- When
output.library.typeor any entry'slibrary.typeis"module"or"modern-module",output.moduleshould default totrue(if not explicitly specified). - If
output.module: falseis explicitly specified withlibrary.type: "module"or"modern-module", webpack should throw a descriptive error (e.g.'library type "module" is only allowed when \'output.module\' is enabled') instead of emitting invalid JavaScript syntax.
Actual Behavior
output.module defaults to false, and webpack wraps the export statement inside an IIFE function, creating invalid JavaScript syntax that fails parsing in JS engines and minifiers.
Environment
System:
OS: macOS 26.6.2
CPU: (8) arm64 Apple M3
Binaries:
Node: 22.23.1
npm: 10.9.8
yarn: 1.22.22
Packages:
webpack: 5.110.3 (main)
Is this a regression?
Yes (please specify version below)
Last Working Version
Introduced in #22011 / commit c4cd6ca4 (when experiments.outputModule was removed)
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Activity
Pcmhacker-piro commentedon Sep 11, 2026
I have opened a PR with the fix, unit tests, and integration test at #22063.
Pcmhacker-piro commentedon Sep 11, 2026
Re-opened clean PR with all checks passing at #22064.