diff --git a/lib/optimize/ConcatenatedModule.js b/lib/optimize/ConcatenatedModule.js index 98dbd7285..dcf76a89a 100644 --- a/lib/optimize/ConcatenatedModule.js +++ b/lib/optimize/ConcatenatedModule.js @@ -550,126 +550,76 @@ class ConcatenatedModule extends Module { /** * @param {Module} rootModule the root module of the concatenation * @param {Set} modules all modules in the concantenation (including the root module) + * @param {ModuleGraph} moduleGraph the module graph + * @param {Object=} associatedObjectForCache object for caching + * @returns {ConcatenatedModule} the module */ - constructor(rootModule, modules) { + static createFromModuleGraph( + rootModule, + modules, + moduleGraph, + associatedObjectForCache + ) { + const orderedConcatenationList = ConcatenatedModule._createConcatenationList( + rootModule, + modules, + moduleGraph + ); + const identifier = ConcatenatedModule._createIdentifier( + rootModule, + orderedConcatenationList, + associatedObjectForCache + ); + return new ConcatenatedModule({ + identifier, + rootModule, + orderedConcatenationList, + modules + }); + } + + /** + * @param {Object} options options + * @param {string} options.identifier the identifier of the module + * @param {Module=} options.rootModule the root module of the concatenation + * @param {Set=} options.modules all concatenated modules + * @param {TODO=} options.orderedConcatenationList the list of concentated modules and externals + */ + constructor({ identifier, rootModule, modules, orderedConcatenationList }) { super("javascript/esm", null); // Info from Factory + /** @type {string} */ + this._identifier = identifier; + /** @type {Module} */ this.rootModule = rootModule; - this.factoryMeta = rootModule.factoryMeta; - /** @private @type {Set} */ + /** @type {Set} */ this._modules = modules; - - const modulesArray = Array.from(modules); - - // Info from Build - this.buildInfo = { - strict: true, - cacheable: modulesArray.every(m => m.buildInfo.cacheable), - moduleArgument: rootModule.buildInfo.moduleArgument, - exportsArgument: rootModule.buildInfo.exportsArgument, - fileDependencies: new LazySet(), - contextDependencies: new LazySet(), - missingDependencies: new LazySet(), - assets: undefined - }; - this.buildMeta = rootModule.buildMeta; + this._orderedConcatenationList = orderedConcatenationList; + this.factoryMeta = rootModule && rootModule.factoryMeta; // Caching - this._numberOfConcatenatedModules = modules.size; /** @private @type {string} */ this._cachedCodeGenerationHash = ""; /** @private @type {CodeGenerationResult} */ this._cachedCodeGeneration = undefined; - - // Graph - this.dependencies = []; - - this._orderedConcatenationList = null; - this._identifier = null; } /** - * @param {Compilation} compilation the compilation + * Assuming this module is in the cache. Update the (cached) module with + * the fresh module from the factory. Usually updates internal references + * and properties. + * @param {Module} module fresh module + * @returns {void} */ - attach(compilation) { - const { rootModule, _modules: modules } = this; - this._orderedConcatenationList = ConcatenatedModule._createConcatenationList( - rootModule, - modules, - compilation - ); - for (const info of this._orderedConcatenationList) { - if (info.type === "concatenated") { - const m = info.module; - - // populate dependencies - for (const d of m.dependencies.filter( - dep => - !(dep instanceof HarmonyImportDependency) || - !modules.has(compilation.moduleGraph.getModule(dep)) - )) { - this.dependencies.push(d); - } - if (m.presentationalDependencies !== undefined) { - for (const d of m.presentationalDependencies.filter( - dep => - !(dep instanceof HarmonyImportDependency) || - !modules.has(compilation.moduleGraph.getModule(dep)) - )) { - this.addPresentationalDependency(d); - } - } - // populate file dependencies - if (m.buildInfo.fileDependencies) { - this.buildInfo.fileDependencies.addAll(m.buildInfo.fileDependencies); - } - // populate context dependencies - if (m.buildInfo.contextDependencies) { - this.buildInfo.contextDependencies.addAll( - m.buildInfo.contextDependencies - ); - } - // populate missing dependencies - if (m.buildInfo.missingDependencies) { - this.buildInfo.missingDependencies.addAll( - m.buildInfo.missingDependencies - ); - } - // populate warnings - const warnings = m.getWarnings(); - if (warnings !== undefined) { - for (const warning of warnings) { - this.addWarning(warning); - } - } - // populate errors - const errors = m.getErrors(); - if (errors !== undefined) { - for (const error of errors) { - this.addError(error); - } - } - - if (m.buildInfo.assets) { - if (this.buildInfo.assets === undefined) { - this.buildInfo.assets = Object.create(null); - } - Object.assign(this.buildInfo.assets, m.buildInfo.assets); - } - if (m.buildInfo.assetsInfo) { - if (this.buildInfo.assetsInfo === undefined) { - this.buildInfo.assetsInfo = new Map(); - } - for (const [key, value] of m.buildInfo.assetsInfo) { - this.buildInfo.assetsInfo.set(key, value); - } - } - } - } - this._identifier = this._createIdentifier(compilation.compiler.root); + updateCacheModule(module) { + super.updateCacheModule(module); + const m = /** @type {ConcatenatedModule} */ (module); + this._identifier = m._identifier; + this.rootModule = m.rootModule; + this._modules = m._modules; + this._orderedConcatenationList = m._orderedConcatenationList; } - /** * @returns {Set} types availiable (do not mutate) */ @@ -697,7 +647,7 @@ class ConcatenatedModule extends Module { readableIdentifier(requestShortener) { return ( this.rootModule.readableIdentifier(requestShortener) + - ` + ${this._numberOfConcatenatedModules - 1} modules` + ` + ${this._modules.size - 1} modules` ); } @@ -725,7 +675,90 @@ class ConcatenatedModule extends Module { * @returns {void} */ build(options, compilation, resolver, fs, callback) { - throw new Error("Cannot build this module. It should be already built."); + const { rootModule } = this; + this.buildInfo = { + strict: true, + cacheable: true, + moduleArgument: rootModule.buildInfo.moduleArgument, + exportsArgument: rootModule.buildInfo.exportsArgument, + fileDependencies: new LazySet(), + contextDependencies: new LazySet(), + missingDependencies: new LazySet(), + assets: undefined + }; + this.buildMeta = rootModule.buildMeta; + this.clearDependenciesAndBlocks(); + this.clearWarningsAndErrors(); + + for (const info of this._orderedConcatenationList) { + if (info.type === "concatenated") { + const m = info.module; + + // populate cacheable + if (!m.buildInfo.cacheable) { + this.buildInfo.cacheable = false; + } + + // populate dependencies + for (const d of m.dependencies.filter( + dep => + !(dep instanceof HarmonyImportDependency) || + !this._modules.has(compilation.moduleGraph.getModule(dep)) + )) { + this.dependencies.push(d); + } + + // populate file dependencies + if (m.buildInfo.fileDependencies) { + this.buildInfo.fileDependencies.addAll(m.buildInfo.fileDependencies); + } + // populate context dependencies + if (m.buildInfo.contextDependencies) { + this.buildInfo.contextDependencies.addAll( + m.buildInfo.contextDependencies + ); + } + // populate missing dependencies + if (m.buildInfo.missingDependencies) { + this.buildInfo.missingDependencies.addAll( + m.buildInfo.missingDependencies + ); + } + + // populate warnings + const warnings = m.getWarnings(); + if (warnings !== undefined) { + for (const warning of warnings) { + this.addWarning(warning); + } + } + + // populate errors + const errors = m.getErrors(); + if (errors !== undefined) { + for (const error of errors) { + this.addError(error); + } + } + + // populate assets + if (m.buildInfo.assets) { + if (this.buildInfo.assets === undefined) { + this.buildInfo.assets = Object.create(null); + } + Object.assign(this.buildInfo.assets, m.buildInfo.assets); + } + if (m.buildInfo.assetsInfo) { + if (this.buildInfo.assetsInfo === undefined) { + this.buildInfo.assetsInfo = new Map(); + } + for (const [key, value] of m.buildInfo.assetsInfo) { + this.buildInfo.assetsInfo.set(key, value); + } + } + } + } + callback(); } /** @@ -749,12 +782,10 @@ class ConcatenatedModule extends Module { * @private * @param {Module} rootModule the root of the concatenation * @param {Set} modulesSet a set of modules which should be concatenated - * @param {Compilation} compilation the compilation context + * @param {ModuleGraph} moduleGraph the module graph * @returns {ConcatenationEntry[]} concatenation list */ - static _createConcatenationList(rootModule, modulesSet, compilation) { - const { moduleGraph } = compilation; - + static _createConcatenationList(rootModule, modulesSet, moduleGraph) { const list = []; const set = new Set(); @@ -813,13 +844,17 @@ class ConcatenatedModule extends Module { return list; } - _createIdentifier(associatedObjectForCache) { + static _createIdentifier( + rootModule, + orderedConcatenationList, + associatedObjectForCache + ) { let orderedConcatenationListIdentifiers = ""; - for (let i = 0; i < this._orderedConcatenationList.length; i++) { - if (this._orderedConcatenationList[i].type === "concatenated") { + for (let i = 0; i < orderedConcatenationList.length; i++) { + if (orderedConcatenationList[i].type === "concatenated") { orderedConcatenationListIdentifiers += contextify( - this.rootModule.context, - this._orderedConcatenationList[i].module.identifier(), + rootModule.context, + orderedConcatenationList[i].module.identifier(), associatedObjectForCache ); orderedConcatenationListIdentifiers += " "; @@ -827,7 +862,7 @@ class ConcatenatedModule extends Module { } const hash = createHash("md4"); hash.update(orderedConcatenationListIdentifiers); - return this.rootModule.identifier() + "|" + hash.digest("hex"); + return rootModule.identifier() + "|" + hash.digest("hex"); } /** @@ -1425,18 +1460,18 @@ class ConcatenatedModule extends Module { serialize(context) { const { write } = context; - // constructor - write(this.rootModule); - write(this.modules); - // deserialize write(this._cachedCodeGenerationHash); write(this._cachedCodeGeneration); super.serialize(context); } static deserialize(context) { - const { read } = context; - const obj = new ConcatenatedModule(read(), new Set(read())); + const obj = new ConcatenatedModule({ + identifier: undefined, + rootModule: undefined, + orderedConcatenationList: undefined, + modules: undefined + }); obj.deserialize(context); return obj; } diff --git a/lib/optimize/ModuleConcatenationPlugin.js b/lib/optimize/ModuleConcatenationPlugin.js index 15d985144..94ce1a965 100644 --- a/lib/optimize/ModuleConcatenationPlugin.js +++ b/lib/optimize/ModuleConcatenationPlugin.js @@ -9,6 +9,7 @@ const asyncLib = require("neo-async"); const ChunkGraph = require("../ChunkGraph"); const ModuleGraph = require("../ModuleGraph"); const ModuleRestoreError = require("../ModuleRestoreError"); +const ModuleStoreError = require("../ModuleStoreError"); const { STAGE_DEFAULT } = require("../OptimizationStages"); const HarmonyCompatibilityDependency = require("../dependencies/HarmonyCompatibilityDependency"); const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency"); @@ -106,10 +107,12 @@ class ModuleConcatenationPlugin { name: "ModuleConcatenationPlugin", stage: STAGE_DEFAULT }, - (allChunks, modules, cb) => { + (allChunks, modules, callback) => { + const logger = compilation.getLogger("ModuleConcatenationPlugin"); const chunkGraph = compilation.chunkGraph; const relevantModules = []; const possibleInners = new Set(); + logger.time("select relevant modules"); for (const module of modules) { // Only harmony modules are valid for optimization if ( @@ -272,12 +275,20 @@ class ModuleConcatenationPlugin { possibleInners.add(module); } + logger.timeEnd("select relevant modules"); + logger.debug( + `${relevantModules.length} potential root modules, ${possibleInners.size} potential inner modules` + ); // sort by depth // modules with lower depth are more likely suited as roots // this improves performance, because modules already selected as inner are skipped + logger.time("sort relevant modules"); relevantModules.sort((a, b) => { return moduleGraph.getDepth(a) - moduleGraph.getDepth(b); }); + logger.timeEnd("sort relevant modules"); + + logger.time("find modules to concatenate"); const concatConfigurations = []; const usedAsInner = new Set(); for (const currentRoot of relevantModules) { @@ -291,18 +302,33 @@ class ModuleConcatenationPlugin { // cache failures to add modules const failureCache = new Map(); + // potential optional import candiates + /** @type {Set} */ + const candidates = new Set(); + // try to add all imports for (const imp of this._getImports(compilation, currentRoot)) { + candidates.add(imp); + } + + for (const imp of candidates) { + // _tryToAdd modifies the config even if it fails + // so make sure to only accept changes when it succeed + const backup = currentConfiguration.snapshot(); const problem = this._tryToAdd( compilation, currentConfiguration, imp, possibleInners, + candidates, failureCache ); if (problem) { failureCache.set(imp, problem); currentConfiguration.addWarning(imp, problem); + + // roll back + currentConfiguration.rollback(backup); } } if (!currentConfiguration.isEmpty()) { @@ -313,42 +339,91 @@ class ModuleConcatenationPlugin { } } } else { + const optimizationBailouts = moduleGraph.getOptimizationBailout( + currentRoot + ); for (const warning of currentConfiguration.getWarningsSorted()) { - moduleGraph - .getOptimizationBailout(currentRoot) - .push(formatBailoutWarning(warning[0], warning[1])); + optimizationBailouts.push( + formatBailoutWarning(warning[0], warning[1]) + ); } } } + logger.timeEnd("find modules to concatenate"); + logger.debug( + `${concatConfigurations.length} concat configurations` + ); // HACK: Sort configurations by length and start with the longest one // to get the biggers groups possible. Used modules are marked with usedModules // TODO: Allow to reuse existing configuration while trying to add dependencies. // This would improve performance. O(n^2) -> O(n) + logger.time(`sort concat configurations`); concatConfigurations.sort((a, b) => { return b.modules.size - a.modules.size; }); + logger.timeEnd(`sort concat configurations`); const usedModules = new Set(); + logger.time("create concatenated modules"); asyncLib.each( concatConfigurations, - (concatConfiguration, cb) => { - if (usedModules.has(concatConfiguration.rootModule)) - return cb(); - const modules = concatConfiguration.getModules(); + (concatConfiguration, callback) => { const rootModule = concatConfiguration.rootModule; - let newModule = new ConcatenatedModule(rootModule, modules); - newModule.attach(compilation); + + // Avoid overlapping configurations + // TODO: remove this when todo above is fixed + if (usedModules.has(rootModule)) return callback(); + const modules = concatConfiguration.getModules(); + for (const m of modules) { + usedModules.add(m); + } + + // Create a new ConcatenatedModule + let newModule = ConcatenatedModule.createFromModuleGraph( + rootModule, + modules, + moduleGraph, + compiler.root + ); + + // get name for caching const identifier = newModule.identifier(); - const cacheName = `${compilation.compilerPath}/concatModule/${identifier}`; - compilation.cache.get(cacheName, null, (err, cacheModule) => { - if (err) return cb(new ModuleRestoreError(newModule, err)); + const cacheName = `${compilation.compilerPath}/ModuleConcatenationPlugin/${identifier}`; - if (cacheModule) { - cacheModule.updateCacheModule(newModule); - newModule = cacheModule; - newModule.attach(compilation); - } + const restore = () => { + compilation.cache.get(cacheName, null, (err, cacheModule) => { + if (err) { + return callback(new ModuleRestoreError(newModule, err)); + } + if (cacheModule) { + cacheModule.updateCacheModule(newModule); + newModule = cacheModule; + } + + build(); + }); + }; + + const build = () => { + newModule.build( + compiler.options, + compilation, + null, + null, + err => { + if (err) { + if (!err.module) { + err.module = newModule; + } + return callback(err); + } + integrateAndStore(); + } + ); + }; + + const integrateAndStore = () => { ChunkGraph.setChunkGraphForModule(newModule, chunkGraph); ModuleGraph.setModuleGraphForModule(newModule, moduleGraph); for (const warning of concatConfiguration.getWarningsSorted()) { @@ -359,7 +434,7 @@ class ModuleConcatenationPlugin { moduleGraph.cloneModuleAttributes(rootModule, newModule); for (const m of modules) { compilation.modules.delete(m); - usedModules.add(m); + // add to builtModules when one of the included modules was built if (compilation.builtModules.has(m)) { compilation.builtModules.add(newModule); @@ -379,13 +454,20 @@ class ModuleConcatenationPlugin { compilation.modules.add(newModule); compilation.cache.store(cacheName, null, newModule, err => { - if (err) return cb(new ModuleRestoreError(newModule, err)); + if (err) { + return callback(new ModuleStoreError(newModule, err)); + } - cb(); + callback(); }); - }); + }; + + restore(); }, - cb + err => { + logger.timeEnd("create concatenated modules"); + process.nextTick(() => callback(err)); + } ); } ); @@ -426,10 +508,18 @@ class ModuleConcatenationPlugin { * @param {ConcatConfiguration} config concat configuration (will be modified when added) * @param {Module} module the module to be added * @param {Set} possibleModules modules that are candidates + * @param {Set} candidates list of potential candidates (will be added to) * @param {Map} failureCache cache for problematic modules to be more performant * @returns {Module} the problematic module */ - _tryToAdd(compilation, config, module, possibleModules, failureCache) { + _tryToAdd( + compilation, + config, + module, + possibleModules, + candidates, + failureCache + ) { const cacheEntry = failureCache.get(module); if (cacheEntry) { return cacheEntry; @@ -446,11 +536,8 @@ class ModuleConcatenationPlugin { return module; } - // Clone config to make experimental changes - const testConfig = config.clone(); - // Add the module - testConfig.add(module); + config.add(module); const moduleGraph = compilation.moduleGraph; @@ -461,9 +548,10 @@ class ModuleConcatenationPlugin { const problem = this._tryToAdd( compilation, - testConfig, + config, connection.originModule, possibleModules, + candidates, failureCache ); if (problem) { @@ -472,21 +560,9 @@ class ModuleConcatenationPlugin { } } - // Commit experimental changes - config.set(testConfig); - - // Eagerly try to add imports too if possible + // Add imports to possible candiates list for (const imp of this._getImports(compilation, module)) { - const problem = this._tryToAdd( - compilation, - config, - imp, - possibleModules, - failureCache - ); - if (problem) { - config.addWarning(imp, problem); - } + candidates.add(imp); } return null; } @@ -496,22 +572,14 @@ class ConcatConfiguration { /** * * @param {Module} rootModule the root module - * @param {ConcatConfiguration=} cloneFrom base config */ - constructor(rootModule, cloneFrom) { + constructor(rootModule) { this.rootModule = rootModule; - if (cloneFrom) { - /** @type {StackedMap} */ - this.modules = cloneFrom.modules.createChild(); - /** @type {StackedMap} */ - this.warnings = cloneFrom.warnings.createChild(); - } else { - /** @type {StackedMap} */ - this.modules = new StackedMap(); - this.modules.set(rootModule, true); - /** @type {StackedMap} */ - this.warnings = new StackedMap(); - } + /** @type {StackedMap} */ + this.modules = new StackedMap(); + this.modules.set(rootModule, true); + /** @type {StackedMap} */ + this.warnings = new StackedMap(); } add(module) { @@ -549,14 +617,14 @@ class ConcatConfiguration { return this.modules.asSet(); } - clone() { - return new ConcatConfiguration(this.rootModule, this); + snapshot() { + const base = this.modules; + this.modules = this.modules.createChild(); + return base; } - set(config) { - this.rootModule = config.rootModule; - this.modules = config.modules; - this.warnings = config.warnings; + rollback(snapshot) { + this.modules = snapshot; } } diff --git a/test/__snapshots__/StatsTestCases.test.js.snap b/test/__snapshots__/StatsTestCases.test.js.snap index 4fac74991..22c06c10e 100644 --- a/test/__snapshots__/StatsTestCases.test.js.snap +++ b/test/__snapshots__/StatsTestCases.test.js.snap @@ -641,26 +641,26 @@ Entrypoint entry-1 = vendor-1.js entry-1.js `; exports[`StatsTestCases should print correct stats for commons-plugin-issue-4980 1`] = ` -"Hash: cc1067a9ed68395a22d361ebf4f77d289ef5d090 +"Hash: 369dce9696722aff8630778eed1bb35adfdf68ee Child - Hash: cc1067a9ed68395a22d3 + Hash: 369dce9696722aff8630 Time: Xms Built at: 1970-04-20 12:42:42 Asset Size - app.e7c3ca90761b75404b15-1.js 5.86 KiB [emitted] [immutable] [name: app] + app.28702b7a86e378694d09-1.js 5.86 KiB [emitted] [immutable] [name: app] vendor.611fd9bad8fe7de29fe7-1.js 615 bytes [emitted] [immutable] [name: vendor] [id hint: vendor] - Entrypoint app = vendor.611fd9bad8fe7de29fe7-1.js app.e7c3ca90761b75404b15-1.js + Entrypoint app = vendor.611fd9bad8fe7de29fe7-1.js app.28702b7a86e378694d09-1.js ./entry-1.js + 2 modules 190 bytes [built] ./constants.js 87 bytes [built] + 3 hidden modules Child - Hash: 61ebf4f77d289ef5d090 + Hash: 778eed1bb35adfdf68ee Time: Xms Built at: 1970-04-20 12:42:42 Asset Size - app.3543b1c65e6a5b58cae6-2.js 5.87 KiB [emitted] [immutable] [name: app] + app.11dd0b201bfcb5fa156a-2.js 5.87 KiB [emitted] [immutable] [name: app] vendor.611fd9bad8fe7de29fe7-2.js 615 bytes [emitted] [immutable] [name: vendor] [id hint: vendor] - Entrypoint app = vendor.611fd9bad8fe7de29fe7-2.js app.3543b1c65e6a5b58cae6-2.js + Entrypoint app = vendor.611fd9bad8fe7de29fe7-2.js app.11dd0b201bfcb5fa156a-2.js ./entry-2.js + 2 modules 197 bytes [built] ./constants.js 87 bytes [built] + 3 hidden modules" @@ -684,52 +684,52 @@ exports[`StatsTestCases should print correct stats for concat-and-sideeffects 1` `; exports[`StatsTestCases should print correct stats for context-independence 1`] = ` -"Hash: 6506665a35d2ca5d31ac6506665a35d2ca5d31accf181f0e0e06350b116acf181f0e0e06350b116a +"Hash: 3bbcc69a5b6015de0e133bbcc69a5b6015de0e13b817462215fe98066a27b817462215fe98066a27 Child - Hash: 6506665a35d2ca5d31ac + Hash: 3bbcc69a5b6015de0e13 Time: Xms Built at: 1970-04-20 12:42:42 Asset Size - 703-3e2afd6460ceb1cd6f5f.js 438 bytes [emitted] [immutable] - 703-3e2afd6460ceb1cd6f5f.js.map 343 bytes [emitted] [dev] - main-a1003986d61ab330d2c5.js 8.14 KiB [emitted] [immutable] [name: main] - main-a1003986d61ab330d2c5.js.map 7.2 KiB [emitted] [dev] [name: (main)] - Entrypoint main = main-a1003986d61ab330d2c5.js (main-a1003986d61ab330d2c5.js.map) + 703-97267ca95e3cfbc183d4.js 438 bytes [emitted] [immutable] + 703-97267ca95e3cfbc183d4.js.map 343 bytes [emitted] [dev] + main-6b11eb1f2bbfff254738.js 8.14 KiB [emitted] [immutable] [name: main] + main-6b11eb1f2bbfff254738.js.map 7.2 KiB [emitted] [dev] [name: (main)] + Entrypoint main = main-6b11eb1f2bbfff254738.js (main-6b11eb1f2bbfff254738.js.map) ./a/index.js 40 bytes [built] ./a/chunk.js + 1 modules 66 bytes [built] + 6 hidden modules Child - Hash: 6506665a35d2ca5d31ac + Hash: 3bbcc69a5b6015de0e13 Time: Xms Built at: 1970-04-20 12:42:42 Asset Size - 703-3e2afd6460ceb1cd6f5f.js 438 bytes [emitted] [immutable] - 703-3e2afd6460ceb1cd6f5f.js.map 343 bytes [emitted] [dev] - main-a1003986d61ab330d2c5.js 8.14 KiB [emitted] [immutable] [name: main] - main-a1003986d61ab330d2c5.js.map 7.2 KiB [emitted] [dev] [name: (main)] - Entrypoint main = main-a1003986d61ab330d2c5.js (main-a1003986d61ab330d2c5.js.map) + 703-97267ca95e3cfbc183d4.js 438 bytes [emitted] [immutable] + 703-97267ca95e3cfbc183d4.js.map 343 bytes [emitted] [dev] + main-6b11eb1f2bbfff254738.js 8.14 KiB [emitted] [immutable] [name: main] + main-6b11eb1f2bbfff254738.js.map 7.2 KiB [emitted] [dev] [name: (main)] + Entrypoint main = main-6b11eb1f2bbfff254738.js (main-6b11eb1f2bbfff254738.js.map) ./b/index.js 40 bytes [built] ./b/chunk.js + 1 modules 66 bytes [built] + 6 hidden modules Child - Hash: cf181f0e0e06350b116a + Hash: b817462215fe98066a27 Time: Xms Built at: 1970-04-20 12:42:42 Asset Size - 703-d51a9ad771055bba3447.js 962 bytes [emitted] [immutable] - main-f8577eeb56b10147974d.js 8.48 KiB [emitted] [immutable] [name: main] - Entrypoint main = main-f8577eeb56b10147974d.js + 703-e96ad695ea376e8e9157.js 962 bytes [emitted] [immutable] + main-856478c0c82303c87701.js 8.48 KiB [emitted] [immutable] [name: main] + Entrypoint main = main-856478c0c82303c87701.js ./a/index.js 40 bytes [built] ./a/chunk.js + 1 modules 66 bytes [built] + 6 hidden modules Child - Hash: cf181f0e0e06350b116a + Hash: b817462215fe98066a27 Time: Xms Built at: 1970-04-20 12:42:42 Asset Size - 703-d51a9ad771055bba3447.js 962 bytes [emitted] [immutable] - main-f8577eeb56b10147974d.js 8.48 KiB [emitted] [immutable] [name: main] - Entrypoint main = main-f8577eeb56b10147974d.js + 703-e96ad695ea376e8e9157.js 962 bytes [emitted] [immutable] + main-856478c0c82303c87701.js 8.48 KiB [emitted] [immutable] [name: main] + Entrypoint main = main-856478c0c82303c87701.js ./b/index.js 40 bytes [built] ./b/chunk.js + 1 modules 66 bytes [built] + 6 hidden modules" @@ -1588,7 +1588,7 @@ If you don't want to include a polyfill, you can use an empty module like this: `; exports[`StatsTestCases should print correct stats for module-reasons 1`] = ` -"Hash: a74cbe7b899ea89c631e +"Hash: 7ad27c2fa358483a7fdd Time: Xms Built at: 1970-04-20 12:42:42 Asset Size @@ -2441,6 +2441,14 @@ LOG from webpack.SplitChunksPlugin modules: Xms queue: Xms maxSize: Xms + +LOG from ModuleConcatenationPlugin + select relevant modules: Xms + sort relevant modules: Xms + find modules to concatenate: Xms + sort concat configurations: Xms + create concatenated modules: Xms ++ 2 hidden lines " `; @@ -2531,7 +2539,7 @@ Entrypoint e2 = runtime.js e2.js" `; exports[`StatsTestCases should print correct stats for scope-hoisting-bailouts 1`] = ` -"Hash: ea361a8a1e8207bed262 +"Hash: 419464d6e886f327e369 Time: Xms Built at: 1970-04-20 12:42:42 Entrypoint index = index.js @@ -2561,7 +2569,7 @@ external \\"external\\" 42 bytes [built] `; exports[`StatsTestCases should print correct stats for scope-hoisting-multi 1`] = ` -"Hash: e2c7355c011145721c930f50cdfccf67cfa8eb2a +"Hash: e2c7355c011145721c93cfe13e3565883e0c5a86 Child Hash: e2c7355c011145721c93 Time: Xms @@ -2581,7 +2589,7 @@ Child ./common_lazy_shared.js 25 bytes [built] + 12 hidden modules Child - Hash: 0f50cdfccf67cfa8eb2a + Hash: cfe13e3565883e0c5a86 Time: Xms Built at: 1970-04-20 12:42:42 Entrypoint first = b-vendor.js b-first.js @@ -2608,7 +2616,7 @@ Child `; exports[`StatsTestCases should print correct stats for side-effects-issue-7428 1`] = ` -"Hash: dd7339ec873427ae72f9 +"Hash: 9ee30c02e5810205c6ce Time: Xms Built at: 1970-04-20 12:42:42 Asset Size @@ -2659,7 +2667,7 @@ Entrypoint main = main.js `; exports[`StatsTestCases should print correct stats for side-effects-simple-unused 1`] = ` -"Hash: 5e65a865b852c4d57af6 +"Hash: bba4214f926bfb74bb29 Time: Xms Built at: 1970-04-20 12:42:42 Asset Size