fix: tree-shakable module library should align preconditions of allowInlineStartup

This commit is contained in:
hai-x 2025-08-04 23:50:05 +08:00 committed by GitHub
parent 9a3c4f9f8b
commit a0189019cc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 451 additions and 117 deletions

View File

@ -115,9 +115,10 @@ const makeSerializable = require("./util/makeSerializable");
* @property {boolean=} strictHarmonyModule * @property {boolean=} strictHarmonyModule
* @property {boolean=} async * @property {boolean=} async
* @property {boolean=} sideEffectFree * @property {boolean=} sideEffectFree
* @property {Record<string, string>=} exportsFinalName
* @property {boolean=} isCSSModule * @property {boolean=} isCSSModule
* @property {Record<string, string>=} jsIncompatibleExports * @property {Record<string, string>=} jsIncompatibleExports
* @property {Record<string, string>=} exportsFinalName
* @property {string=} factoryExportsBinding
*/ */
/** /**

View File

@ -18,6 +18,7 @@ const memoize = require("./util/memoize");
/** @typedef {import("./ModuleGraph")} ModuleGraph */ /** @typedef {import("./ModuleGraph")} ModuleGraph */
/** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */ /** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */
/** @typedef {import("./javascript/JavascriptModulesPlugin").ChunkRenderContext} ChunkRenderContext */ /** @typedef {import("./javascript/JavascriptModulesPlugin").ChunkRenderContext} ChunkRenderContext */
/** @typedef {import("./javascript/JavascriptModulesPlugin").ModuleRenderContext} ModuleRenderContext */
/** @typedef {import("./util/Hash")} Hash */ /** @typedef {import("./util/Hash")} Hash */
/** /**
@ -44,7 +45,7 @@ class ModuleTemplate {
/** /**
* @template AdditionalOptions * @template AdditionalOptions
* @param {string | Tap & IfSet<AdditionalOptions>} options options * @param {string | Tap & IfSet<AdditionalOptions>} options options
* @param {(source: Source, module: Module, chunkRenderContext: ChunkRenderContext, dependencyTemplates: DependencyTemplates) => Source} fn fn * @param {(source: Source, module: Module, moduleRenderContext: ModuleRenderContext, dependencyTemplates: DependencyTemplates) => Source} fn fn
*/ */
(options, fn) => { (options, fn) => {
getJavascriptModulesPlugin() getJavascriptModulesPlugin()
@ -69,7 +70,7 @@ class ModuleTemplate {
/** /**
* @template AdditionalOptions * @template AdditionalOptions
* @param {string | Tap & IfSet<AdditionalOptions>} options options * @param {string | Tap & IfSet<AdditionalOptions>} options options
* @param {(source: Source, module: Module, chunkRenderContext: ChunkRenderContext, dependencyTemplates: DependencyTemplates) => Source} fn fn * @param {(source: Source, module: Module, moduleRenderContext: ModuleRenderContext, dependencyTemplates: DependencyTemplates) => Source} fn fn
*/ */
(options, fn) => { (options, fn) => {
getJavascriptModulesPlugin() getJavascriptModulesPlugin()

View File

@ -173,13 +173,38 @@ const printGeneratedCodeForStack = (module, code) => {
* @property {string} hash hash to be used for render call * @property {string} hash hash to be used for render call
*/ */
/** @typedef {RenderContext & { inlined: boolean }} StartupRenderContext */ /**
* @typedef {object} StartupRenderContext
* @property {Chunk} chunk the chunk
* @property {DependencyTemplates} dependencyTemplates the dependency templates
* @property {RuntimeTemplate} runtimeTemplate the runtime template
* @property {ModuleGraph} moduleGraph the module graph
* @property {ChunkGraph} chunkGraph the chunk graph
* @property {CodeGenerationResults} codeGenerationResults results of code generation
* @property {boolean | undefined} strictMode rendering in strict context
* @property {boolean } inlined inlined
* @property {boolean=} inlinedInIIFE the inlined entry module is wrapped in an IIFE
*/
/**
* @typedef {object} ModuleRenderContext
* @property {Chunk} chunk the chunk
* @property {DependencyTemplates} dependencyTemplates the dependency templates
* @property {RuntimeTemplate} runtimeTemplate the runtime template
* @property {ModuleGraph} moduleGraph the module graph
* @property {ChunkGraph} chunkGraph the chunk graph
* @property {CodeGenerationResults} codeGenerationResults results of code generation
* @property {InitFragment<ChunkRenderContext>[]} chunkInitFragments init fragments for the chunk
* @property {boolean | undefined} strictMode rendering in strict context
* @property {boolean} factory true: renders as factory method, false: pure module content
* @property {boolean=} inlinedInIIFE the inlined entry module is wrapped in an IIFE, existing only when `factory` is set to false
*/
/** /**
* @typedef {object} CompilationHooks * @typedef {object} CompilationHooks
* @property {SyncWaterfallHook<[Source, Module, ChunkRenderContext]>} renderModuleContent * @property {SyncWaterfallHook<[Source, Module, ModuleRenderContext]>} renderModuleContent
* @property {SyncWaterfallHook<[Source, Module, ChunkRenderContext]>} renderModuleContainer * @property {SyncWaterfallHook<[Source, Module, ModuleRenderContext]>} renderModuleContainer
* @property {SyncWaterfallHook<[Source, Module, ChunkRenderContext]>} renderModulePackage * @property {SyncWaterfallHook<[Source, Module, ModuleRenderContext]>} renderModulePackage
* @property {SyncWaterfallHook<[Source, RenderContext]>} renderChunk * @property {SyncWaterfallHook<[Source, RenderContext]>} renderChunk
* @property {SyncWaterfallHook<[Source, RenderContext]>} renderMain * @property {SyncWaterfallHook<[Source, RenderContext]>} renderMain
* @property {SyncWaterfallHook<[Source, RenderContext]>} renderContent * @property {SyncWaterfallHook<[Source, RenderContext]>} renderContent
@ -217,17 +242,17 @@ class JavascriptModulesPlugin {
renderModuleContent: new SyncWaterfallHook([ renderModuleContent: new SyncWaterfallHook([
"source", "source",
"module", "module",
"renderContext" "moduleRenderContext"
]), ]),
renderModuleContainer: new SyncWaterfallHook([ renderModuleContainer: new SyncWaterfallHook([
"source", "source",
"module", "module",
"renderContext" "moduleRenderContext"
]), ]),
renderModulePackage: new SyncWaterfallHook([ renderModulePackage: new SyncWaterfallHook([
"source", "source",
"module", "module",
"renderContext" "moduleRenderContext"
]), ]),
render: new SyncWaterfallHook(["source", "renderContext"]), render: new SyncWaterfallHook(["source", "renderContext"]),
renderContent: new SyncWaterfallHook(["source", "renderContext"]), renderContent: new SyncWaterfallHook(["source", "renderContext"]),
@ -575,18 +600,18 @@ class JavascriptModulesPlugin {
/** /**
* @param {Module} module the rendered module * @param {Module} module the rendered module
* @param {ChunkRenderContext} renderContext options object * @param {ModuleRenderContext} renderContext options object
* @param {CompilationHooks} hooks hooks * @param {CompilationHooks} hooks hooks
* @param {boolean} factory true: renders as factory method, false: pure module content
* @returns {Source | null} the newly generated source from rendering * @returns {Source | null} the newly generated source from rendering
*/ */
renderModule(module, renderContext, hooks, factory) { renderModule(module, renderContext, hooks) {
const { const {
chunk, chunk,
chunkGraph, chunkGraph,
runtimeTemplate, runtimeTemplate,
codeGenerationResults, codeGenerationResults,
strictMode strictMode,
factory
} = renderContext; } = renderContext;
try { try {
const codeGenResult = codeGenerationResults.get(module, chunk.runtime); const codeGenResult = codeGenerationResults.get(module, chunk.runtime);
@ -729,7 +754,11 @@ class JavascriptModulesPlugin {
}; };
const moduleSources = const moduleSources =
Template.renderChunkModules(chunkRenderContext, allModules, (module) => Template.renderChunkModules(chunkRenderContext, allModules, (module) =>
this.renderModule(module, chunkRenderContext, hooks, true) this.renderModule(
module,
{ ...chunkRenderContext, factory: true },
hooks
)
) || new RawSource("{}"); ) || new RawSource("{}");
let source = tryRunOrWebpackError( let source = tryRunOrWebpackError(
() => hooks.renderChunk.call(moduleSources, chunkRenderContext), () => hooks.renderChunk.call(moduleSources, chunkRenderContext),
@ -841,7 +870,12 @@ class JavascriptModulesPlugin {
(m) => !(/** @type {Set<Module>} */ (inlinedModules).has(m)) (m) => !(/** @type {Set<Module>} */ (inlinedModules).has(m))
) )
: allModules, : allModules,
(module) => this.renderModule(module, chunkRenderContext, hooks, true), (module) =>
this.renderModule(
module,
{ ...chunkRenderContext, factory: true },
hooks
),
prefix prefix
); );
if ( if (
@ -913,6 +947,8 @@ class JavascriptModulesPlugin {
const avoidEntryIife = compilation.options.optimization.avoidEntryIife; const avoidEntryIife = compilation.options.optimization.avoidEntryIife;
/** @type {Map<Module, Source> | false} */ /** @type {Map<Module, Source> | false} */
let renamedInlinedModule = false; let renamedInlinedModule = false;
let inlinedInIIFE = false;
if (avoidEntryIife) { if (avoidEntryIife) {
renamedInlinedModule = this.getRenamedInlineModule( renamedInlinedModule = this.getRenamedInlineModule(
allModules, allModules,
@ -926,13 +962,6 @@ class JavascriptModulesPlugin {
} }
for (const m of inlinedModules) { for (const m of inlinedModules) {
const renderedModule = renamedInlinedModule
? renamedInlinedModule.get(m)
: this.renderModule(m, chunkRenderContext, hooks, false);
if (renderedModule) {
const innerStrict =
!allStrict && /** @type {BuildInfo} */ (m.buildInfo).strict;
const runtimeRequirements = chunkGraph.getModuleRuntimeRequirements( const runtimeRequirements = chunkGraph.getModuleRuntimeRequirements(
m, m,
chunk.runtime chunk.runtime
@ -940,6 +969,10 @@ class JavascriptModulesPlugin {
const exports = runtimeRequirements.has(RuntimeGlobals.exports); const exports = runtimeRequirements.has(RuntimeGlobals.exports);
const webpackExports = const webpackExports =
exports && m.exportsArgument === RuntimeGlobals.exports; exports && m.exportsArgument === RuntimeGlobals.exports;
const innerStrict =
!allStrict && /** @type {BuildInfo} */ (m.buildInfo).strict;
const iife = innerStrict const iife = innerStrict
? "it needs to be in strict mode." ? "it needs to be in strict mode."
: inlinedModules.size > 1 : inlinedModules.size > 1
@ -951,6 +984,24 @@ class JavascriptModulesPlugin {
: exports && !webpackExports : exports && !webpackExports
? `it uses a non-standard name for the exports (${m.exportsArgument}).` ? `it uses a non-standard name for the exports (${m.exportsArgument}).`
: hooks.embedInRuntimeBailout.call(m, renderContext); : hooks.embedInRuntimeBailout.call(m, renderContext);
if (iife) {
inlinedInIIFE = true;
}
const renderedModule = renamedInlinedModule
? renamedInlinedModule.get(m)
: this.renderModule(
m,
{
...chunkRenderContext,
factory: false,
inlinedInIIFE
},
hooks
);
if (renderedModule) {
let footer; let footer;
if (iife !== undefined) { if (iife !== undefined) {
startupSource.add( startupSource.add(
@ -989,7 +1040,8 @@ class JavascriptModulesPlugin {
source.add( source.add(
hooks.renderStartup.call(startupSource, lastInlinedModule, { hooks.renderStartup.call(startupSource, lastInlinedModule, {
...renderContext, ...renderContext,
inlined: true inlined: true,
inlinedInIIFE
}) })
); );
if (bootstrap.afterStartup.length > 0) { if (bootstrap.afterStartup.length > 0) {
@ -1557,7 +1609,6 @@ class JavascriptModulesPlugin {
allModules.every((m) => /** @type {BuildInfo} */ (m.buildInfo).strict); allModules.every((m) => /** @type {BuildInfo} */ (m.buildInfo).strict);
const isMultipleEntries = inlinedModules.size > 1; const isMultipleEntries = inlinedModules.size > 1;
const singleEntryWithModules = inlinedModules.size === 1 && hasChunkModules; const singleEntryWithModules = inlinedModules.size === 1 && hasChunkModules;
// TODO: // TODO:
// This step is before the IIFE reason calculation. Ideally, it should only be executed when this function can optimize the // This step is before the IIFE reason calculation. Ideally, it should only be executed when this function can optimize the
// IIFE reason. Otherwise, it should directly return false. There are four reasons now, we have skipped two already, the left // IIFE reason. Otherwise, it should directly return false. There are four reasons now, we have skipped two already, the left
@ -1581,9 +1632,12 @@ class JavascriptModulesPlugin {
const isInlinedModule = inlinedModules && inlinedModules.has(m); const isInlinedModule = inlinedModules && inlinedModules.has(m);
const moduleSource = this.renderModule( const moduleSource = this.renderModule(
m, m,
chunkRenderContext, {
hooks, ...chunkRenderContext,
!isInlinedModule factory: !isInlinedModule,
inlinedInIIFE: false
},
hooks
); );
if (!moduleSource) continue; if (!moduleSource) continue;

View File

@ -19,6 +19,8 @@ const JavascriptModulesPlugin = require("../javascript/JavascriptModulesPlugin")
/** @typedef {import("../Module")} Module */ /** @typedef {import("../Module")} Module */
/** @typedef {import("../javascript/JavascriptModulesPlugin").RenderContext} RenderContext */ /** @typedef {import("../javascript/JavascriptModulesPlugin").RenderContext} RenderContext */
/** @typedef {import("../javascript/JavascriptModulesPlugin").StartupRenderContext} StartupRenderContext */ /** @typedef {import("../javascript/JavascriptModulesPlugin").StartupRenderContext} StartupRenderContext */
/** @typedef {import("../javascript/JavascriptModulesPlugin").ChunkRenderContext} ChunkRenderContext */
/** @typedef {import("../javascript/JavascriptModulesPlugin").ModuleRenderContext} ModuleRenderContext */
/** @typedef {import("../util/Hash")} Hash */ /** @typedef {import("../util/Hash")} Hash */
const COMMON_LIBRARY_NAME_MESSAGE = const COMMON_LIBRARY_NAME_MESSAGE =
@ -173,6 +175,20 @@ class AbstractLibraryPlugin {
}); });
} }
if (
this.renderModuleContent !==
AbstractLibraryPlugin.prototype.renderModuleContent
) {
hooks.renderModuleContent.tap(
_pluginName,
(source, module, renderContext) =>
this.renderModuleContent(source, module, renderContext, {
compilation,
chunkGraph: compilation.chunkGraph
})
);
}
if ( if (
this.renderStartup !== AbstractLibraryPlugin.prototype.renderStartup this.renderStartup !== AbstractLibraryPlugin.prototype.renderStartup
) { ) {
@ -288,6 +304,17 @@ class AbstractLibraryPlugin {
return source; return source;
} }
/**
* @param {Source} source source
* @param {Module} module module
* @param {ModuleRenderContext} renderContext render context
* @param {Omit<LibraryContext<T>, 'options'>} libraryContext context
* @returns {Source} source with library export
*/
renderModuleContent(source, module, renderContext, libraryContext) {
return source;
}
/** /**
* @param {Chunk} chunk the chunk * @param {Chunk} chunk the chunk
* @param {Hash} hash hash * @param {Hash} hash hash

View File

@ -8,7 +8,6 @@
const { ConcatSource } = require("webpack-sources"); const { ConcatSource } = require("webpack-sources");
const RuntimeGlobals = require("../RuntimeGlobals"); const RuntimeGlobals = require("../RuntimeGlobals");
const Template = require("../Template"); const Template = require("../Template");
const JavascriptModulesPlugin = require("../javascript/JavascriptModulesPlugin");
const ConcatenatedModule = require("../optimize/ConcatenatedModule"); const ConcatenatedModule = require("../optimize/ConcatenatedModule");
const propertyAccess = require("../util/propertyAccess"); const propertyAccess = require("../util/propertyAccess");
const AbstractLibraryPlugin = require("./AbstractLibraryPlugin"); const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");
@ -22,6 +21,7 @@ const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");
/** @typedef {import("../Module")} Module */ /** @typedef {import("../Module")} Module */
/** @typedef {import("../Module").BuildMeta} BuildMeta */ /** @typedef {import("../Module").BuildMeta} BuildMeta */
/** @typedef {import("../javascript/JavascriptModulesPlugin").StartupRenderContext} StartupRenderContext */ /** @typedef {import("../javascript/JavascriptModulesPlugin").StartupRenderContext} StartupRenderContext */
/** @typedef {import("../javascript/JavascriptModulesPlugin").ModuleRenderContext} ModuleRenderContext */
/** @typedef {import("../util/Hash")} Hash */ /** @typedef {import("../util/Hash")} Hash */
/** /**
@ -66,37 +66,9 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
super.apply(compiler); super.apply(compiler);
compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => { compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
const { exportsDefinitions } = const { onDemandExportsGeneration } =
ConcatenatedModule.getCompilationHooks(compilation); ConcatenatedModule.getCompilationHooks(compilation);
exportsDefinitions.tap(PLUGIN_NAME, (definitions, module) => { onDemandExportsGeneration.tap(PLUGIN_NAME, (_module) => true);
const bailout = JavascriptModulesPlugin.getCompilationHooks(
compilation
).inlineInRuntimeBailout.call(module, {});
if (bailout) return false;
// If we have connections not all modules were concatenated, so we need the wrapper
const connections =
compilation.moduleGraph.getIncomingConnections(module);
for (const connection of connections) {
if (connection.originModule) {
return false;
}
}
// Runtime and splitting chunks now requires the wrapper too
for (const chunk of compilation.chunkGraph.getModuleChunksIterable(
module
)) {
if (
!chunk.hasRuntime() ||
compilation.chunkGraph.getNumberOfEntryModules(chunk) > 1
) {
return false;
}
}
return true;
});
}); });
} }
@ -128,7 +100,7 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
renderStartup( renderStartup(
source, source,
module, module,
{ moduleGraph, chunk, codeGenerationResults }, { moduleGraph, chunk, codeGenerationResults, inlined, inlinedInIIFE },
{ options, compilation } { options, compilation }
) { ) {
const result = new ConcatSource(source); const result = new ConcatSource(source);
@ -141,8 +113,11 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
] ]
: moduleGraph.getExportsInfo(module).orderedExports; : moduleGraph.getExportsInfo(module).orderedExports;
const definitions = const definitions =
/** @type {BuildMeta} */ inlined && !inlinedInIIFE
(module.buildMeta).exportsFinalName || {}; ? (module.buildMeta &&
/** @type {GenerationMeta} */ module.buildMeta.exportsFinalName) ||
{}
: {};
/** @type {string[]} */ /** @type {string[]} */
const shortHandedExports = []; const shortHandedExports = [];
/** @type {[string, string][]} */ /** @type {[string, string][]} */
@ -241,6 +216,32 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
return result; return result;
} }
/**
* @param {Source} source source
* @param {Module} module module
* @param {ModuleRenderContext} renderContext render context
* @param {Omit<LibraryContext<T>, 'options'>} libraryContext context
* @returns {Source} source with library export
*/
renderModuleContent(
source,
module,
{ factory, inlinedInIIFE },
libraryContext
) {
const result = new ConcatSource(source);
// Re-add `factoryExportsBinding` to the source
// when the module is rendered as a factory or treated as an inlined (startup) module but wrapped in an IIFE
if (
(inlinedInIIFE || factory) &&
module.buildMeta &&
module.buildMeta.factoryExportsBinding
) {
result.add(module.buildMeta.factoryExportsBinding);
}
return result;
}
} }
module.exports = ModuleLibraryPlugin; module.exports = ModuleLibraryPlugin;

View File

@ -668,7 +668,7 @@ const getFinalName = (
/** /**
* @typedef {object} ConcatenateModuleHooks * @typedef {object} ConcatenateModuleHooks
* @property {SyncBailHook<[Record<string, string>, ConcatenatedModule], boolean | void>} exportsDefinitions * @property {SyncBailHook<[ConcatenatedModule], boolean>} onDemandExportsGeneration
* @property {SyncBailHook<[Partial<ConcatenatedModuleInfo>, ConcatenatedModuleInfo], boolean | void>} concatenatedModuleInfo * @property {SyncBailHook<[Partial<ConcatenatedModuleInfo>, ConcatenatedModuleInfo], boolean | void>} concatenatedModuleInfo
*/ */
@ -716,7 +716,7 @@ class ConcatenatedModule extends Module {
let hooks = compilationHooksMap.get(compilation); let hooks = compilationHooksMap.get(compilation);
if (hooks === undefined) { if (hooks === undefined) {
hooks = { hooks = {
exportsDefinitions: new SyncBailHook(["definitions", "module"]), onDemandExportsGeneration: new SyncBailHook(["module"]),
concatenatedModuleInfo: new SyncBailHook([ concatenatedModuleInfo: new SyncBailHook([
"updatedInfo", "updatedInfo",
"concatenatedModuleInfo" "concatenatedModuleInfo"
@ -1692,11 +1692,6 @@ class ConcatenatedModule extends Module {
// define exports // define exports
if (exportsMap.size > 0) { if (exportsMap.size > 0) {
const { exportsDefinitions } = ConcatenatedModule.getCompilationHooks(
/** @type {Compilation} */
(this.compilation)
);
const definitions = []; const definitions = [];
for (const [key, value] of exportsMap) { for (const [key, value] of exportsMap) {
definitions.push( definitions.push(
@ -1706,12 +1701,12 @@ class ConcatenatedModule extends Module {
); );
} }
const shouldSkipRenderDefinitions = exportsDefinitions.call( const { onDemandExportsGeneration } =
exportsFinalName, ConcatenatedModule.getCompilationHooks(
this /** @type {Compilation} */
(this.compilation)
); );
if (!shouldSkipRenderDefinitions) {
runtimeRequirements.add(RuntimeGlobals.exports); runtimeRequirements.add(RuntimeGlobals.exports);
runtimeRequirements.add(RuntimeGlobals.definePropertyGetters); runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
@ -1725,15 +1720,20 @@ class ConcatenatedModule extends Module {
); );
} }
if (onDemandExportsGeneration.call(this)) {
/** @type {BuildMeta} */ (this.buildMeta).factoryExportsBinding =
`${RuntimeGlobals.definePropertyGetters}(${
this.exportsArgument
}, {${definitions.join(",")}\n});\n`;
/** @type {BuildMeta} */ (this.buildMeta).exportsFinalName =
exportsFinalName;
} else {
result.add("\n// EXPORTS\n"); result.add("\n// EXPORTS\n");
result.add( result.add(
`${RuntimeGlobals.definePropertyGetters}(${ `${RuntimeGlobals.definePropertyGetters}(${
this.exportsArgument this.exportsArgument
}, {${definitions.join(",")}\n});\n` }, {${definitions.join(",")}\n});\n`
); );
} else {
/** @type {BuildMeta} */
(this.buildMeta).exportsFinalName = exportsFinalName;
} }
} }

View File

@ -10155,6 +10155,29 @@ import { HomeLayout as HomeLayout_0, a as a_0 } from \\"externals1\\";
import { default as default_0 } from \\"externals2\\"; import { default as default_0 } from \\"externals2\\";
import * as __WEBPACK_EXTERNAL_MODULE_externals3__ from \\"externals3\\"; import * as __WEBPACK_EXTERNAL_MODULE_externals3__ from \\"externals3\\";
import \\"externals4\\"; import \\"externals4\\";
/******/ // The require scope
/******/ var __webpack_require__ = {};
/******/
/************************************************************************/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/************************************************************************/
var __webpack_exports__ = {};
/*!*****************************!*\\\\ /*!*****************************!*\\\\
!*** ./test.js + 6 modules ***! !*** ./test.js + 6 modules ***!
\\\\*****************************/ \\\\*****************************/
@ -10229,6 +10252,29 @@ import { HomeLayout as HomeLayout_0, a as a_0 } from \\"externals1\\";
import { default as default_0 } from \\"externals2\\"; import { default as default_0 } from \\"externals2\\";
import * as __WEBPACK_EXTERNAL_MODULE_externals3__ from \\"externals3\\"; import * as __WEBPACK_EXTERNAL_MODULE_externals3__ from \\"externals3\\";
import \\"externals4\\"; import \\"externals4\\";
/******/ // The require scope
/******/ var __webpack_require__ = {};
/******/
/************************************************************************/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/************************************************************************/
var __webpack_exports__ = {};
/*!*****************************!*\\\\ /*!*****************************!*\\\\
!*** ./test.js + 6 modules ***! !*** ./test.js + 6 modules ***!
\\\\*****************************/ \\\\*****************************/
@ -10303,6 +10349,29 @@ import { HomeLayout as HomeLayout_0, a as a_0 } from \\"externals1\\";
import { default as default_0 } from \\"externals2\\"; import { default as default_0 } from \\"externals2\\";
import * as __WEBPACK_EXTERNAL_MODULE_externals3__ from \\"externals3\\"; import * as __WEBPACK_EXTERNAL_MODULE_externals3__ from \\"externals3\\";
import \\"externals4\\"; import \\"externals4\\";
/******/ // The require scope
/******/ var __webpack_require__ = {};
/******/
/************************************************************************/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/************************************************************************/
var __webpack_exports__ = {};
/*!*****************************!*\\\\ /*!*****************************!*\\\\
!*** ./test.js + 6 modules ***! !*** ./test.js + 6 modules ***!
\\\\*****************************/ \\\\*****************************/
@ -10377,6 +10446,29 @@ import { HomeLayout as HomeLayout_0, a as a_0 } from \\"externals1\\";
import { default as default_0 } from \\"externals2\\"; import { default as default_0 } from \\"externals2\\";
import * as __WEBPACK_EXTERNAL_MODULE_externals3__ from \\"externals3\\"; import * as __WEBPACK_EXTERNAL_MODULE_externals3__ from \\"externals3\\";
import \\"externals4\\"; import \\"externals4\\";
/******/ // The require scope
/******/ var __webpack_require__ = {};
/******/
/************************************************************************/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/************************************************************************/
var __webpack_exports__ = {};
/*!*****************************!*\\\\ /*!*****************************!*\\\\
!*** ./test.js + 6 modules ***! !*** ./test.js + 6 modules ***!
\\\\*****************************/ \\\\*****************************/

View File

@ -10155,6 +10155,29 @@ import { HomeLayout as HomeLayout_0, a as a_0 } from \\"externals1\\";
import { default as default_0 } from \\"externals2\\"; import { default as default_0 } from \\"externals2\\";
import * as __WEBPACK_EXTERNAL_MODULE_externals3__ from \\"externals3\\"; import * as __WEBPACK_EXTERNAL_MODULE_externals3__ from \\"externals3\\";
import \\"externals4\\"; import \\"externals4\\";
/******/ // The require scope
/******/ var __webpack_require__ = {};
/******/
/************************************************************************/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/************************************************************************/
var __webpack_exports__ = {};
/*!*****************************!*\\\\ /*!*****************************!*\\\\
!*** ./test.js + 6 modules ***! !*** ./test.js + 6 modules ***!
\\\\*****************************/ \\\\*****************************/

View File

@ -64,6 +64,29 @@ module.exports = (env, { testPath }) => [
outputModule: true outputModule: true
} }
}, },
{
entry: "./esm-with-commonjs.js",
output: {
uniqueName: "esm-with-commonjs",
filename: "esm-with-commonjs-avoid-entry-iife.js",
library: {
type: "module"
}
},
target: "node14",
resolve: {
alias: {
external: "./non-external",
"external-named": "./non-external-named"
}
},
optimization: {
avoidEntryIife: false
},
experiments: {
outputModule: true
}
},
{ {
output: { output: {
uniqueName: "esm-export", uniqueName: "esm-export",

View File

@ -76,6 +76,22 @@ module.exports = (env, { testPath }) => [
}) })
] ]
}, },
{
entry: "./esm-with-commonjs",
resolve: {
alias: {
library: path.resolve(
testPath,
"../0-create-library/esm-with-commonjs-avoid-entry-iife.js"
)
}
},
plugins: [
new webpack.DefinePlugin({
NAME: JSON.stringify("esm-with-commonjs")
})
]
},
{ {
entry: "./module-export-test.js", entry: "./module-export-test.js",
resolve: { resolve: {

126
types.d.ts vendored
View File

@ -160,6 +160,12 @@ declare class AbstractLibraryPlugin<T> {
renderContext: StartupRenderContext, renderContext: StartupRenderContext,
libraryContext: LibraryContext<T> libraryContext: LibraryContext<T>
): Source; ): Source;
renderModuleContent(
source: Source,
module: Module,
renderContext: ModuleRenderContext,
libraryContext: Omit<LibraryContext<T>, "options">
): Source;
chunkHash( chunkHash(
chunk: Chunk, chunk: Chunk,
hash: Hash, hash: Hash,
@ -2549,15 +2555,11 @@ declare interface CompilationHooksCssModulesPlugin {
chunkHash: SyncHook<[Chunk, Hash, ChunkHashContext]>; chunkHash: SyncHook<[Chunk, Hash, ChunkHashContext]>;
} }
declare interface CompilationHooksJavascriptModulesPlugin { declare interface CompilationHooksJavascriptModulesPlugin {
renderModuleContent: SyncWaterfallHook< renderModuleContent: SyncWaterfallHook<[Source, Module, ModuleRenderContext]>;
[Source, Module, ChunkRenderContextJavascriptModulesPlugin]
>;
renderModuleContainer: SyncWaterfallHook< renderModuleContainer: SyncWaterfallHook<
[Source, Module, ChunkRenderContextJavascriptModulesPlugin] [Source, Module, ModuleRenderContext]
>;
renderModulePackage: SyncWaterfallHook<
[Source, Module, ChunkRenderContextJavascriptModulesPlugin]
>; >;
renderModulePackage: SyncWaterfallHook<[Source, Module, ModuleRenderContext]>;
renderChunk: SyncWaterfallHook< renderChunk: SyncWaterfallHook<
[Source, RenderContextJavascriptModulesPlugin] [Source, RenderContextJavascriptModulesPlugin]
>; >;
@ -6461,9 +6463,8 @@ declare class JavascriptModulesPlugin {
apply(compiler: Compiler): void; apply(compiler: Compiler): void;
renderModule( renderModule(
module: Module, module: Module,
renderContext: ChunkRenderContextJavascriptModulesPlugin, renderContext: ModuleRenderContext,
hooks: CompilationHooksJavascriptModulesPlugin, hooks: CompilationHooksJavascriptModulesPlugin
factory: boolean
): null | Source; ): null | Source;
renderChunk( renderChunk(
renderContext: RenderContextJavascriptModulesPlugin, renderContext: RenderContextJavascriptModulesPlugin,
@ -8355,9 +8356,10 @@ declare interface KnownBuildMeta {
strictHarmonyModule?: boolean; strictHarmonyModule?: boolean;
async?: boolean; async?: boolean;
sideEffectFree?: boolean; sideEffectFree?: boolean;
exportsFinalName?: Record<string, string>;
isCSSModule?: boolean; isCSSModule?: boolean;
jsIncompatibleExports?: Record<string, string>; jsIncompatibleExports?: Record<string, string>;
exportsFinalName?: Record<string, string>;
factoryExportsBinding?: string;
} }
declare interface KnownCreateStatsOptionsContext { declare interface KnownCreateStatsOptionsContext {
forToString?: boolean; forToString?: boolean;
@ -10355,6 +10357,57 @@ declare interface ModuleReferenceOptions {
*/ */
asiSafe?: boolean; asiSafe?: boolean;
} }
declare interface ModuleRenderContext {
/**
* the chunk
*/
chunk: Chunk;
/**
* the dependency templates
*/
dependencyTemplates: DependencyTemplates;
/**
* the runtime template
*/
runtimeTemplate: RuntimeTemplate;
/**
* the module graph
*/
moduleGraph: ModuleGraph;
/**
* the chunk graph
*/
chunkGraph: ChunkGraph;
/**
* results of code generation
*/
codeGenerationResults: CodeGenerationResults;
/**
* init fragments for the chunk
*/
chunkInitFragments: InitFragment<ChunkRenderContextJavascriptModulesPlugin>[];
/**
* rendering in strict context
*/
strictMode?: boolean;
/**
* true: renders as factory method, false: pure module content
*/
factory: boolean;
/**
* the inlined entry module is wrapped in an IIFE, existing only when `factory` is set to false
*/
inlinedInIIFE?: boolean;
}
declare interface ModuleResult { declare interface ModuleResult {
client: string; client: string;
data: string; data: string;
@ -10402,7 +10455,7 @@ declare abstract class ModuleTemplate {
fn: ( fn: (
source: Source, source: Source,
module: Module, module: Module,
chunkRenderContext: ChunkRenderContextJavascriptModulesPlugin, moduleRenderContext: ModuleRenderContext,
dependencyTemplates: DependencyTemplates dependencyTemplates: DependencyTemplates
) => Source ) => Source
) => void; ) => void;
@ -10415,7 +10468,7 @@ declare abstract class ModuleTemplate {
fn: ( fn: (
source: Source, source: Source,
module: Module, module: Module,
chunkRenderContext: ChunkRenderContextJavascriptModulesPlugin, moduleRenderContext: ModuleRenderContext,
dependencyTemplates: DependencyTemplates dependencyTemplates: DependencyTemplates
) => Source ) => Source
) => void; ) => void;
@ -15976,9 +16029,52 @@ declare abstract class StackedMap<K, V> {
get size(): number; get size(): number;
createChild(): StackedMap<K, V>; createChild(): StackedMap<K, V>;
} }
type StartupRenderContext = RenderContextJavascriptModulesPlugin & { declare interface StartupRenderContext {
/**
* the chunk
*/
chunk: Chunk;
/**
* the dependency templates
*/
dependencyTemplates: DependencyTemplates;
/**
* the runtime template
*/
runtimeTemplate: RuntimeTemplate;
/**
* the module graph
*/
moduleGraph: ModuleGraph;
/**
* the chunk graph
*/
chunkGraph: ChunkGraph;
/**
* results of code generation
*/
codeGenerationResults: CodeGenerationResults;
/**
* rendering in strict context
*/
strictMode?: boolean;
/**
* inlined
*/
inlined: boolean; inlined: boolean;
};
/**
* the inlined entry module is wrapped in an IIFE
*/
inlinedInIIFE?: boolean;
}
declare interface StatFs { declare interface StatFs {
( (
path: PathLikeFs, path: PathLikeFs,