diff --git a/lib/Chunk.js b/lib/Chunk.js index cb90d8daf..dc17206dd 100644 --- a/lib/Chunk.js +++ b/lib/Chunk.js @@ -66,8 +66,6 @@ class Chunk { this.name = name; /** @type {boolean} */ this.preventIntegration = false; - /** @type {Module=} */ - this.entryModule = undefined; /** @type {string?} */ this.filenameTemplate = undefined; /** @private @type {SortableSet} */ @@ -125,13 +123,6 @@ class Chunk { return true; } - /** - * @returns {boolean} if this chunk contains the entry module - */ - hasEntryModule() { - return !!this.entryModule; - } - /** * @param {ChunkGroup} chunkGroup the chunkGroup the chunk is being added * @returns {boolean} returns true if chunk is not apart of chunkGroup and is added successfully @@ -168,7 +159,7 @@ class Chunk { } /** - * @returns {SortableSet} the chunkGroups that said chunk is referenced in + * @returns {Iterable} the chunkGroups that said chunk is referenced in */ get groupsIterable() { return this._groups; @@ -209,40 +200,14 @@ class Chunk { )) { hash.update(m.hash); } - } - - canBeIntegrated(otherChunk) { - const isAvailable = (a, b) => { - const queue = new Set(b.groupsIterable); - for (const chunkGroup of queue) { - if (a.isInGroup(chunkGroup)) continue; - if (chunkGroup.isInitial()) return false; - for (const parent of chunkGroup.parentsIterable) { - queue.add(parent); - } - } - return true; - }; - - if (this.preventIntegration || otherChunk.preventIntegration) { - return false; + const entryModules = chunkGraph.getChunkEntryModulesWithChunkGroupIterable( + this + ); + for (const [m, chunkGroup] of entryModules) { + hash.update("entry"); + hash.update(m.hash); + hash.update(chunkGroup.id); } - - if (this.hasRuntime() !== otherChunk.hasRuntime()) { - if (this.hasRuntime()) { - return isAvailable(this, otherChunk); - } else if (otherChunk.hasRuntime()) { - return isAvailable(otherChunk, this); - } else { - return false; - } - } - - if (this.hasEntryModule() || otherChunk.hasEntryModule()) { - return false; - } - - return true; } /** @@ -284,7 +249,7 @@ class Chunk { */ /** - * @param {boolean} realHash should the full hash or the rendered hash be used + * @param {boolean=} realHash should the full hash or the rendered hash be used * @returns {ChunkMaps} the chunk map information */ getChunkMaps(realHash) { diff --git a/lib/ChunkGraph.js b/lib/ChunkGraph.js index c3dadc3a0..c521fa651 100644 --- a/lib/ChunkGraph.js +++ b/lib/ChunkGraph.js @@ -70,6 +70,8 @@ class ChunkGraphModule { constructor() { /** @type {SortableSet} */ this.chunks = new SortableSet(); + /** @type {Set} */ + this.entryInChunks = new Set(); } } @@ -77,6 +79,8 @@ class ChunkGraphChunk { constructor() { /** @type {SortableSet} */ this.modules = new SortableSet(); + /** @type {Map} */ + this.entryModules = new Map(); } } @@ -177,14 +181,30 @@ class ChunkGraph { replaceModule(oldModule, newModule) { const oldCgm = this._getChunkGraphModule(oldModule); const newCgm = this._getChunkGraphModule(newModule); - const chunks = this.getModuleChunks(oldModule); - for (const chunk of chunks) { + + for (const chunk of oldCgm.chunks) { const cgc = this._getChunkGraphChunk(chunk); cgc.modules.delete(oldModule); cgc.modules.add(newModule); - oldCgm.chunks.delete(chunk); newCgm.chunks.add(chunk); } + oldCgm.chunks.clear(); + + for (const chunk of oldCgm.entryInChunks) { + const cgc = this._getChunkGraphChunk(chunk); + const old = cgc.entryModules.get(oldModule); + const newEntryModules = new Map(); + for (const [m, cg] of cgc.entryModules) { + if (m === oldModule) { + newEntryModules.set(newModule, old); + } else { + newEntryModules.set(m, cg); + } + } + cgc.entryModules = newEntryModules; + newCgm.entryInChunks.add(chunk); + } + oldCgm.entryInChunks.clear(); } /** @@ -215,10 +235,7 @@ class ChunkGraph { */ isEntryModule(module) { const cgm = this._getChunkGraphModule(module); - for (const chunk of cgm.chunks) { - if (chunk.entryModule === module) return true; - } - return false; + return cgm.entryInChunks.size > 0; } /** @@ -501,7 +518,45 @@ class ChunkGraph { * @returns {boolean} true, if chunks could be integrated */ canChunksBeIntegrated(chunkA, chunkB) { - return chunkA.canBeIntegrated(chunkB); + /** + * @param {Chunk} a chunk + * @param {Chunk} b chunk + * @returns {boolean} true, if a is always a parent of b + */ + const isAvailable = (a, b) => { + const queue = new Set(b.groupsIterable); + for (const chunkGroup of queue) { + if (a.isInGroup(chunkGroup)) continue; + if (chunkGroup.isInitial()) return false; + for (const parent of chunkGroup.parentsIterable) { + queue.add(parent); + } + } + return true; + }; + + if (chunkA.preventIntegration || chunkB.preventIntegration) { + return false; + } + + if (chunkA.hasRuntime() !== chunkB.hasRuntime()) { + if (chunkA.hasRuntime()) { + return isAvailable(chunkA, chunkB); + } else if (chunkB.hasRuntime()) { + return isAvailable(chunkB, chunkA); + } else { + return false; + } + } + + if ( + this.getNumberOfEntryModules(chunkA) > 0 || + this.getNumberOfEntryModules(chunkB) > 0 + ) { + return false; + } + + return true; } /** @@ -532,6 +587,84 @@ class ChunkGraph { } } } + + /** + * @param {Module} module the checked module + * @param {Chunk} chunk the checked chunk + * @returns {boolean} true, if the chunk contains the module as entry + */ + isEntryModuleInChunk(module, chunk) { + const cgc = this._getChunkGraphChunk(chunk); + return cgc.entryModules.has(module); + } + + /** + * @param {Chunk} chunk the new chunk + * @param {Module} module the entry module + * @param {ChunkGroup=} chunkGroup the chunk group which must be loaded before the module is executed + * @returns {void} + */ + connectChunkAndEntryModule(chunk, module, chunkGroup) { + const cgm = this._getChunkGraphModule(module); + const cgc = this._getChunkGraphChunk(chunk); + cgm.entryInChunks.add(chunk); + cgc.entryModules.set(module, chunkGroup); + } + + /** + * @param {Module} module the entry module, it will no longer be entry + * @returns {void} + */ + disconnectEntryModule(module) { + const cgm = this._getChunkGraphModule(module); + for (const chunk of cgm.entryInChunks) { + const cgc = this._getChunkGraphChunk(chunk); + cgc.entryModules.delete(module); + } + cgm.entryInChunks.clear(); + } + + /** + * @param {Chunk} chunk the chunk, for which all entries will be removed + * @returns {void} + */ + disconnectEntries(chunk) { + const cgc = this._getChunkGraphChunk(chunk); + for (const module of cgc.entryModules.keys()) { + const cgm = this._getChunkGraphModule(module); + cgm.entryInChunks.delete(chunk); + } + cgc.entryModules.clear(); + } + + /** + * @param {Chunk} chunk the chunk + * @returns {number} the amount of entry modules in chunk + */ + getNumberOfEntryModules(chunk) { + const cgc = this._getChunkGraphChunk(chunk); + return cgc.entryModules.size; + } + + /** + * @param {Chunk} chunk the chunk + * @returns {Iterable} iterable of modules (do not modify) + */ + getChunkEntryModulesIterable(chunk) { + const cgc = this._getChunkGraphChunk(chunk); + return cgc.entryModules.keys(); + } + + /** @typedef {[Module, ChunkGroup | undefined]} EntryModuleWithChunkGroup */ + + /** + * @param {Chunk} chunk the chunk + * @returns {Iterable} iterable of modules (do not modify) + */ + getChunkEntryModulesWithChunkGroupIterable(chunk) { + const cgc = this._getChunkGraphChunk(chunk); + return cgc.entryModules; + } } module.exports = ChunkGraph; diff --git a/lib/ChunkGroup.js b/lib/ChunkGroup.js index c9af6317f..4c7f4a081 100644 --- a/lib/ChunkGroup.js +++ b/lib/ChunkGroup.js @@ -348,10 +348,9 @@ class ChunkGroup { } /** - * @param {string=} reason reason for removing ChunkGroup * @returns {void} */ - remove(reason) { + remove() { // cleanup parents for (const parentChunkGroup of this._parents) { // remove this chunk from its parents diff --git a/lib/ChunkTemplate.js b/lib/ChunkTemplate.js index ff0ca1ba4..7970c066e 100644 --- a/lib/ChunkTemplate.js +++ b/lib/ChunkTemplate.js @@ -14,16 +14,8 @@ const { SyncWaterfallHook, SyncHook } = require("tapable"); /** @typedef {import("./DependencyTemplates")} DependencyTemplates} */ /** @typedef {import("webpack-sources").Source} Source} */ /** @typedef {import("./ModuleTemplate").RenderContext} RenderContext} */ - -/** - * @typedef {Object} RenderManifestOptions - * @property {Chunk} chunk the chunk used to render - * @property {string} hash - * @property {string} fullHash - * @property {TODO} outputOptions - * @property {{javascript: ModuleTemplate, webassembly: ModuleTemplate}} moduleTemplates - * @property {DependencyTemplates} dependencyTemplates - */ +/** @typedef {import("./Template").RenderManifestOptions} RenderManifestOptions} */ +/** @typedef {import("./Template").RenderManifestEntry} RenderManifestEntry} */ module.exports = class ChunkTemplate { constructor(outputOptions) { @@ -52,7 +44,7 @@ module.exports = class ChunkTemplate { /** * * @param {RenderManifestOptions} options render manifest options - * @returns {TODO[]} returns render manifest + * @returns {RenderManifestEntry[]} returns render manifest */ getRenderManifest(options) { const result = []; diff --git a/lib/Compilation.js b/lib/Compilation.js index 34a84fc4a..47f990530 100644 --- a/lib/Compilation.js +++ b/lib/Compilation.js @@ -37,7 +37,6 @@ const ModuleTemplate = require("./ModuleTemplate"); const RuntimeTemplate = require("./RuntimeTemplate"); const Stats = require("./Stats"); const compareLocations = require("./compareLocations"); -const ModuleDependency = require("./dependencies/ModuleDependency"); const Queue = require("./util/Queue"); const Semaphore = require("./util/Semaphore"); const SortableSet = require("./util/SortableSet"); @@ -54,8 +53,7 @@ const createHash = require("./util/createHash"); /** @typedef {import("./WebpackError")} WebpackError */ /** @typedef {import("./dependencies/DependencyReference")} DependencyReference */ /** @typedef {import("./dependencies/DllEntryDependency")} DllEntryDependency */ -/** @typedef {import("./dependencies/MultiEntryDependency")} MultiEntryDependency */ -/** @typedef {import("./dependencies/SingleEntryDependency")} SingleEntryDependency */ +/** @typedef {import("./dependencies/EntryDependency")} EntryDependency */ /** @typedef {import("./util/createHash").Hash} Hash */ // TODO use @callback @@ -383,6 +381,7 @@ class Compilation { this.outputOptions, this.requestShortener ); + /** @type {{javascript: ModuleTemplate, webassembly: ModuleTemplate}} */ this.moduleTemplates = { javascript: new ModuleTemplate(this.runtimeTemplate, "javascript"), webassembly: new ModuleTemplate(this.runtimeTemplate, "webassembly") @@ -393,10 +392,9 @@ class Compilation { this.semaphore = new Semaphore(options.parallelism || 100); - this.entries = []; - /** @private @type {{name: string, request: string, module: Module}[]} */ - this._preparedEntrypoints = []; - /** @private @type {Map} */ + /** @type {Map} */ + this.entryDependencies = new Map(); + /** @type {Map} */ this.entrypoints = new Map(); /** @type {Chunk[]} */ this.chunks = []; @@ -931,6 +929,11 @@ class Compilation { currentProfile.factory = afterFactory - start; } + if (!module) { + this.semaphore.release(); + return process.nextTick(callback); + } + const addModuleResult = this.addModule(module); module = addModuleResult.module; @@ -987,53 +990,20 @@ class Compilation { /** * * @param {string} context context path for entry - * @param {Dependency} entry entry dependency being created + * @param {EntryDependency} entry entry dependency being created * @param {string} name name of entry * @param {ModuleCallback} callback callback function * @returns {void} returns */ addEntry(context, entry, name, callback) { - const slot = { - name: name, - // TODO webpack 5 remove `request` - request: null, - module: null - }; - - if (entry instanceof ModuleDependency) { - slot.request = entry.request; + let entriesArray = this.entryDependencies.get(name); + if (entriesArray === undefined) { + entriesArray = []; + this.entryDependencies.set(name, entriesArray); } + entriesArray.push(entry); - // TODO webpack 5: merge modules instead when multiple entry modules are supported - const idx = this._preparedEntrypoints.findIndex(slot => slot.name === name); - if (idx >= 0) { - // Overwrite existing entrypoint - this._preparedEntrypoints[idx] = slot; - } else { - this._preparedEntrypoints.push(slot); - } - this._addModuleChain( - context, - entry, - module => { - this.entries.push(module); - }, - (err, module) => { - if (err) { - return callback(err); - } - - if (module) { - slot.module = module; - } else { - const idx = this._preparedEntrypoints.indexOf(slot); - if (idx >= 0) { - this._preparedEntrypoints.splice(idx, 1); - } - } - return callback(null, module); - } - ); + this._addModuleChain(context, entry, module => {}, callback); } /** @@ -1138,24 +1108,26 @@ class Compilation { this.hooks.afterOptimizeDependencies.call(this.modules); this.hooks.beforeChunks.call(); - for (const preparedEntrypoint of this._preparedEntrypoints) { - const module = preparedEntrypoint.module; - const name = preparedEntrypoint.name; + for (const [name, dependencies] of this.entryDependencies) { const chunk = this.addChunk(name); + chunk.name = name; const entrypoint = new Entrypoint(name); entrypoint.setRuntimeChunk(chunk); - entrypoint.addOrigin(null, { name }, preparedEntrypoint.request); this.namedChunkGroups.set(name, entrypoint); this.entrypoints.set(name, entrypoint); this.chunkGroups.push(entrypoint); - connectChunkGroupAndChunk(entrypoint, chunk); - chunkGraph.connectChunkAndModule(chunk, module); - chunk.entryModule = module; - chunk.name = name; + for (const dep of dependencies) { + entrypoint.addOrigin(null, { name }, dep.request); - this.assignDepth(module); + const module = this.moduleGraph.getModule(dep); + if (module) { + chunkGraph.connectChunkAndModule(chunk, module); + chunkGraph.connectChunkAndEntryModule(chunk, module, entrypoint); + this.assignDepth(module); + } + } } this.processDependenciesBlocksForChunkGroups(this.chunkGroups.slice()); this.sortModules(this.modules); @@ -1565,20 +1537,30 @@ class Compilation { */ /** + * @param {QueueItem[]} queue the queue array (will be mutated) * @param {ChunkGroup} chunkGroup chunk group - * @returns {QueueItem} queue item + * @returns {QueueItem[]} the queue array again */ - const chunkGroupToQueueItem = chunkGroup => ({ - action: ENTER_MODULE, - block: chunkGroup.chunks[0].entryModule, - module: chunkGroup.chunks[0].entryModule, - chunk: chunkGroup.chunks[0], - chunkGroup - }); + const reduceChunkGroupToQueueItem = (queue, chunkGroup) => { + for (const chunk of chunkGroup.chunks) { + for (const module of chunkGraph.getChunkEntryModulesIterable(chunk)) { + queue.push({ + action: ENTER_MODULE, + block: module, + module, + chunk, + chunkGroup + }); + } + } + return queue; + }; // Start with the provided modules/chunks /** @type {QueueItem[]} */ - let queue = inputChunkGroups.map(chunkGroupToQueueItem).reverse(); + let queue = inputChunkGroups + .reduce(reduceChunkGroupToQueueItem, []) + .reverse(); /** @type {QueueItem[]} */ let queueDelayed = []; @@ -1853,7 +1835,7 @@ class Compilation { if (idx >= 0) this.chunks.splice(idx, 1); chunkGraph.disconnectChunk(chunk); } - chunkGroup.remove("unconnected"); + chunkGroup.remove(); } } } @@ -2254,7 +2236,10 @@ class Compilation { fullHash: this.fullHash, outputOptions, moduleTemplates: this.moduleTemplates, - dependencyTemplates: this.dependencyTemplates + dependencyTemplates: this.dependencyTemplates, + chunkGraph: this.chunkGraph, + moduleGraph: this.moduleGraph, + runtimeTemplate: this.runtimeTemplate }); // [{ render(), filenameTemplate, pathOptions, identifier, hash }] for (const fileManifest of manifest) { const cacheName = fileManifest.identifier; @@ -2364,6 +2349,8 @@ class Compilation { } checkConstraints() { + const chunkGraph = this.chunkGraph; + /** @type {Set} */ const usedIds = new Set(); @@ -2385,6 +2372,22 @@ class Compilation { `checkConstraints: duplicate chunk in compilation ${chunk.debugId}` ); } + for (const module of chunkGraph.getChunkModulesIterable(chunk)) { + if (this.modules.indexOf(module) < 0) { + throw new Error( + "checkConstraints: module in chunk but not in compilation " + + ` ${chunk.debugId} ${module.debugId}` + ); + } + } + for (const module of chunkGraph.getChunkEntryModulesIterable(chunk)) { + if (this.modules.indexOf(module) < 0) { + throw new Error( + "checkConstraints: entry module in chunk but not in compilation " + + ` ${chunk.debugId} ${module.debugId}` + ); + } + } } for (const chunkGroup of this.chunkGroups) { diff --git a/lib/DllEntryPlugin.js b/lib/DllEntryPlugin.js index 0f5861381..8422f1ab0 100644 --- a/lib/DllEntryPlugin.js +++ b/lib/DllEntryPlugin.js @@ -7,7 +7,7 @@ const DllModuleFactory = require("./DllModuleFactory"); const DllEntryDependency = require("./dependencies/DllEntryDependency"); -const SingleEntryDependency = require("./dependencies/SingleEntryDependency"); +const EntryDependency = require("./dependencies/EntryDependency"); class DllEntryPlugin { constructor(context, entries, name) { @@ -26,7 +26,7 @@ class DllEntryPlugin { dllModuleFactory ); compilation.dependencyFactories.set( - SingleEntryDependency, + EntryDependency, normalModuleFactory ); } @@ -36,7 +36,7 @@ class DllEntryPlugin { this.context, new DllEntryDependency( this.entries.map((e, idx) => { - const dep = new SingleEntryDependency(e); + const dep = new EntryDependency(e); dep.loc = { name: this.name, index: idx diff --git a/lib/DynamicEntryPlugin.js b/lib/DynamicEntryPlugin.js index 2696a345a..ec5045b86 100644 --- a/lib/DynamicEntryPlugin.js +++ b/lib/DynamicEntryPlugin.js @@ -5,11 +5,8 @@ "use strict"; -const MultiEntryPlugin = require("./MultiEntryPlugin"); -const MultiModuleFactory = require("./MultiModuleFactory"); -const SingleEntryPlugin = require("./SingleEntryPlugin"); -const MultiEntryDependency = require("./dependencies/MultiEntryDependency"); -const SingleEntryDependency = require("./dependencies/SingleEntryDependency"); +const EntryPlugin = require("./EntryPlugin"); +const EntryDependency = require("./dependencies/EntryDependency"); /** @typedef {import("./Compiler")} Compiler */ /** @typedef {import("./Compiler").EntryOptionValuesFunction} EntryOptionValuesFunction */ @@ -32,14 +29,8 @@ class DynamicEntryPlugin { compiler.hooks.compilation.tap( "DynamicEntryPlugin", (compilation, { normalModuleFactory }) => { - const multiModuleFactory = new MultiModuleFactory(); - compilation.dependencyFactories.set( - MultiEntryDependency, - multiModuleFactory - ); - compilation.dependencyFactories.set( - SingleEntryDependency, + EntryDependency, normalModuleFactory ); } @@ -51,29 +42,35 @@ class DynamicEntryPlugin { /** * @param {string|string[]} entry entry value or array of entry values * @param {string} name name of entry - * @returns {Promise} returns the promise resolving the Compilation#addEntry function + * @returns {Promise} returns the promise resolving the Compilation#addEntry function */ const addEntry = (entry, name) => { - const dep = DynamicEntryPlugin.createDependency(entry, name); + const deps = DynamicEntryPlugin.createDependencies(entry, name); return new Promise((resolve, reject) => { - compilation.addEntry(this.context, dep, name, err => { - if (err) return reject(err); - resolve(); - }); + for (const dep of deps) { + compilation.addEntry(this.context, dep, name, err => { + if (err) return reject(err); + resolve(); + }); + } }); }; Promise.resolve(this.entry()).then(entry => { if (typeof entry === "string" || Array.isArray(entry)) { - addEntry(entry, "main").then(() => callback(), callback); + addEntry(entry, "main").then(() => { + callback(); + }, callback); } else if (typeof entry === "object") { Promise.all( Object.keys(entry).map(name => { return addEntry(entry[name], name); }) - ).then(() => callback(), callback); + ).then(() => { + callback(); + }, callback); } - }); + }, callback); } ); } @@ -81,14 +78,11 @@ class DynamicEntryPlugin { /** * @param {string|string[]} entry entry value or array of entry paths * @param {string} name name of entry - * @returns {SingleEntryDependency|MultiEntryDependency} returns dep + * @returns {EntryDependency[]} dependencies */ - static createDependency(entry, name) { - if (Array.isArray(entry)) { - return MultiEntryPlugin.createDependency(entry, name); - } else { - return SingleEntryPlugin.createDependency(entry, name); - } + static createDependencies(entry, name) { + const entryArray = Array.isArray(entry) ? entry : [entry]; + return entryArray.map(entry => EntryPlugin.createDependency(entry, name)); } } diff --git a/lib/EntryOptionPlugin.js b/lib/EntryOptionPlugin.js index 81e01aa6d..00c75911a 100644 --- a/lib/EntryOptionPlugin.js +++ b/lib/EntryOptionPlugin.js @@ -6,24 +6,10 @@ "use strict"; const DynamicEntryPlugin = require("./DynamicEntryPlugin"); -const MultiEntryPlugin = require("./MultiEntryPlugin"); -const SingleEntryPlugin = require("./SingleEntryPlugin"); +const EntryPlugin = require("./EntryPlugin"); /** @typedef {import("./Compiler")} Compiler */ -/** - * @param {string} context context path - * @param {string | string[]} item entry array or single path - * @param {string} name entry key name - * @returns {SingleEntryPlugin | MultiEntryPlugin} returns either a single or multi entry plugin - */ -const itemToPlugin = (context, item, name) => { - if (Array.isArray(item)) { - return new MultiEntryPlugin(context, item, name); - } - return new SingleEntryPlugin(context, item, name); -}; - module.exports = class EntryOptionPlugin { /** * @param {Compiler} compiler the compiler instance one is tapping into @@ -31,11 +17,26 @@ module.exports = class EntryOptionPlugin { */ apply(compiler) { compiler.hooks.entryOption.tap("EntryOptionPlugin", (context, entry) => { + /** + * @param {string | string[]} entry entry array or single path + * @param {string} name entry key name + * @returns {void} + */ + const applyEntryPlugins = (entry, name) => { + if (typeof entry === "string") { + new EntryPlugin(context, entry, name).apply(compiler); + } else if (Array.isArray(entry)) { + for (const item of entry) { + applyEntryPlugins(item, name); + } + } + }; + if (typeof entry === "string" || Array.isArray(entry)) { - itemToPlugin(context, entry, "main").apply(compiler); + applyEntryPlugins(entry, "main"); } else if (typeof entry === "object") { for (const name of Object.keys(entry)) { - itemToPlugin(context, entry[name], name).apply(compiler); + applyEntryPlugins(entry[name], name); } } else if (typeof entry === "function") { new DynamicEntryPlugin(context, entry).apply(compiler); diff --git a/lib/SingleEntryPlugin.js b/lib/EntryPlugin.js similarity index 59% rename from lib/SingleEntryPlugin.js rename to lib/EntryPlugin.js index d36e9ee9b..378c3852b 100644 --- a/lib/SingleEntryPlugin.js +++ b/lib/EntryPlugin.js @@ -5,14 +5,14 @@ "use strict"; -const SingleEntryDependency = require("./dependencies/SingleEntryDependency"); +const EntryDependency = require("./dependencies/EntryDependency"); /** @typedef {import("./Compiler")} Compiler */ -class SingleEntryPlugin { +class EntryPlugin { /** * An entry plugin which will handle - * creation of the SingleEntryDependency + * creation of the EntryDependency * * @param {string} context context path * @param {string} entry entry path @@ -30,36 +30,33 @@ class SingleEntryPlugin { */ apply(compiler) { compiler.hooks.compilation.tap( - "SingleEntryPlugin", + "EntryPlugin", (compilation, { normalModuleFactory }) => { compilation.dependencyFactories.set( - SingleEntryDependency, + EntryDependency, normalModuleFactory ); } ); - compiler.hooks.make.tapAsync( - "SingleEntryPlugin", - (compilation, callback) => { - const { entry, name, context } = this; + compiler.hooks.make.tapAsync("EntryPlugin", (compilation, callback) => { + const { entry, name, context } = this; - const dep = SingleEntryPlugin.createDependency(entry, name); - compilation.addEntry(context, dep, name, callback); - } - ); + const dep = EntryPlugin.createDependency(entry, name); + compilation.addEntry(context, dep, name, callback); + }); } /** * @param {string} entry entry request * @param {string} name entry name - * @returns {SingleEntryDependency} the dependency + * @returns {EntryDependency} the dependency */ static createDependency(entry, name) { - const dep = new SingleEntryDependency(entry); + const dep = new EntryDependency(entry); dep.loc = { name }; return dep; } } -module.exports = SingleEntryPlugin; +module.exports = EntryPlugin; diff --git a/lib/ExtendedAPIPlugin.js b/lib/ExtendedAPIPlugin.js index 15580315c..8f4b5ccb2 100644 --- a/lib/ExtendedAPIPlugin.js +++ b/lib/ExtendedAPIPlugin.js @@ -13,6 +13,8 @@ const NullFactory = require("./NullFactory"); const Template = require("./Template"); const ConstDependency = require("./dependencies/ConstDependency"); +/** @typedef {import("./Compiler")} Compiler */ + const REPLACEMENTS = { // eslint-disable-next-line camelcase __webpack_hash__: "__webpack_require__.h", @@ -27,6 +29,10 @@ const REPLACEMENT_TYPES = { }; class ExtendedAPIPlugin { + /** + * @param {Compiler} compiler webpack compiler + * @returns {void} + */ apply(compiler) { compiler.hooks.compilation.tap( "ExtendedAPIPlugin", @@ -40,7 +46,7 @@ class ExtendedAPIPlugin { const mainTemplate = compilation.mainTemplate; mainTemplate.hooks.requireExtensions.tap( "ExtendedAPIPlugin", - (source, chunk, hash) => { + (source, { chunk, hash }) => { const buf = [source]; buf.push(""); buf.push("// __webpack_hash__"); diff --git a/lib/ExternalModule.js b/lib/ExternalModule.js index 01df67442..bff441402 100644 --- a/lib/ExternalModule.js +++ b/lib/ExternalModule.js @@ -123,10 +123,11 @@ class ExternalModule extends Module { /** * @param {Chunk} chunk the chunk which condition should be checked + * @param {Compilation} compilation the compilation * @returns {boolean} true, if the chunk is ok for the module */ - chunkCondition(chunk) { - return chunk.hasEntryModule(); + chunkCondition(chunk, { chunkGraph }) { + return chunkGraph.getNumberOfEntryModules(chunk) > 0; } /** diff --git a/lib/FlagDependencyUsagePlugin.js b/lib/FlagDependencyUsagePlugin.js index 6b7d1f91b..b987af57f 100644 --- a/lib/FlagDependencyUsagePlugin.js +++ b/lib/FlagDependencyUsagePlugin.js @@ -120,9 +120,13 @@ class FlagDependencyUsagePlugin { /** @type {[Module, DependenciesBlock, UsedExports][]} */ const queue = []; - for (const preparedEntrypoint of compilation._preparedEntrypoints) { - if (preparedEntrypoint.module) { - processModule(preparedEntrypoint.module, true); + for (const [, deps] of compilation.entryDependencies) { + const lastDependency = deps[deps.length - 1]; + if (lastDependency) { + const module = moduleGraph.getModule(lastDependency); + if (module) { + processModule(module, true); + } } } diff --git a/lib/HotModuleReplacementPlugin.js b/lib/HotModuleReplacementPlugin.js index 314b5e051..b8d411334 100644 --- a/lib/HotModuleReplacementPlugin.js +++ b/lib/HotModuleReplacementPlugin.js @@ -380,7 +380,7 @@ module.exports = class HotModuleReplacementPlugin { mainTemplate.hooks.bootstrap.tap( "HotModuleReplacementPlugin", - (source, chunk, hash) => { + (source, moduleTemplate, { chunk, hash }) => { source = mainTemplate.hooks.hotBootstrap.call(source, chunk, hash); return Template.asString([ source, @@ -417,7 +417,7 @@ module.exports = class HotModuleReplacementPlugin { mainTemplate.hooks.moduleObj.tap( "HotModuleReplacementPlugin", - (source, chunk, hash, varModuleId) => { + (source, varModuleId) => { return Template.asString([ `${source},`, `hot: hotCreateModule(${varModuleId}),`, diff --git a/lib/JavascriptModulesPlugin.js b/lib/JavascriptModulesPlugin.js index fcdf136de..786e17076 100644 --- a/lib/JavascriptModulesPlugin.js +++ b/lib/JavascriptModulesPlugin.js @@ -101,12 +101,14 @@ class JavascriptModulesPlugin { result.push({ render: () => - compilation.mainTemplate.render( + compilation.mainTemplate.render(moduleTemplates.javascript, { hash, chunk, - moduleTemplates.javascript, - dependencyTemplates - ), + dependencyTemplates, + runtimeTemplate: options.runtimeTemplate, + moduleGraph: options.moduleGraph, + chunkGraph: options.chunkGraph + }), filenameTemplate, pathOptions: { noChunkHash: !useChunkHash, @@ -121,15 +123,9 @@ class JavascriptModulesPlugin { ); compilation.mainTemplate.hooks.modules.tap( "JavascriptModulesPlugin", - (source, chunk, hash, moduleTemplate, dependencyTemplates) => { + (source, moduleTemplate, renderContext) => { return Template.renderChunkModules( - { - chunk, - dependencyTemplates, - runtimeTemplate: compilation.runtimeTemplate, - moduleGraph: compilation.moduleGraph, - chunkGraph: compilation.chunkGraph - }, + renderContext, m => typeof m.source === "function", moduleTemplate, "/******/ " @@ -233,7 +229,7 @@ class JavascriptModulesPlugin { renderContext ); const chunk = renderContext.chunk; - if (chunk.hasEntryModule()) { + if (renderContext.chunkGraph.getNumberOfEntryModules(chunk) > 0) { source = chunkTemplate.hooks.renderWithEntry.call(source, chunk); } chunk.rendered = true; diff --git a/lib/LibManifestPlugin.js b/lib/LibManifestPlugin.js index 5fc3cca5f..9018ade2c 100644 --- a/lib/LibManifestPlugin.js +++ b/lib/LibManifestPlugin.js @@ -7,7 +7,7 @@ const asyncLib = require("neo-async"); const path = require("path"); -const SingleEntryDependency = require("./dependencies/SingleEntryDependency"); +const EntryDependency = require("./dependencies/EntryDependency"); const { compareModulesById } = require("./util/comparators"); class LibManifestPlugin { @@ -50,7 +50,7 @@ class LibManifestPlugin { this.options.entryOnly && !compilation.moduleGraph .getIncomingConnections(module) - .some(c => c.dependency instanceof SingleEntryDependency) + .some(c => c.dependency instanceof EntryDependency) ) { return; } diff --git a/lib/MainTemplate.js b/lib/MainTemplate.js index 58093c693..641781752 100644 --- a/lib/MainTemplate.js +++ b/lib/MainTemplate.js @@ -21,15 +21,21 @@ const Template = require("./Template"); /** @typedef {import("./Module")} Module} */ /** @typedef {import("./util/createHash").Hash} Hash} */ /** @typedef {import("./DependencyTemplates")} DependencyTemplates} */ +/** @typedef {import("./ModuleTemplate").RenderContext} RenderContext} */ +/** @typedef {import("./RuntimeTemplate")} RuntimeTemplate} */ +/** @typedef {import("./ModuleGraph")} ModuleGraph} */ +/** @typedef {import("./ChunkGraph")} ChunkGraph} */ +/** @typedef {import("./Template").RenderManifestOptions} RenderManifestOptions} */ +/** @typedef {import("./Template").RenderManifestEntry} RenderManifestEntry} */ /** - * @typedef {Object} RenderManifestOptions - * @property {Chunk} chunk the chunk used to render - * @property {string} hash - * @property {string} fullHash - * @property {TODO} outputOptions - * @property {{javascript: ModuleTemplate, webassembly: ModuleTemplate}} moduleTemplates - * @property {DependencyTemplates} dependencyTemplates + * @typedef {Object} MainRenderContext + * @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 {string} hash hash to be used for render call */ // require function shortcuts: @@ -60,45 +66,44 @@ module.exports = class MainTemplate { this.hooks = Object.freeze({ /** @type {SyncWaterfallHook} */ renderManifest: new SyncWaterfallHook(["result", "options"]), + /** @type {SyncWaterfallHook} */ modules: new SyncWaterfallHook([ - "modules", - "chunk", - "hash", + "source", "moduleTemplate", - "dependencyTemplates" + "renderContext" ]), + /** @type {SyncWaterfallHook} */ moduleObj: new SyncWaterfallHook([ "source", - "chunk", - "hash", - "moduleIdExpression" + "moduleIdExpression", + "renderContext" ]), + /** @type {SyncWaterfallHook} */ requireEnsure: new SyncWaterfallHook([ "source", - "chunk", - "hash", - "chunkIdExpression" + "chunkIdExpression", + "renderContext" ]), + /** @type {SyncWaterfallHook} */ bootstrap: new SyncWaterfallHook([ "source", - "chunk", - "hash", "moduleTemplate", - "dependencyTemplates" + "renderContext" ]), localVars: new SyncWaterfallHook(["source", "chunk", "hash"]), - require: new SyncWaterfallHook(["source", "chunk", "hash"]), - requireExtensions: new SyncWaterfallHook(["source", "chunk", "hash"]), + /** @type {SyncWaterfallHook} */ + require: new SyncWaterfallHook(["source", "renderContext"]), + /** @type {SyncWaterfallHook} */ + requireExtensions: new SyncWaterfallHook(["source", "renderContext"]), /** @type {SyncWaterfallHook} */ beforeStartup: new SyncWaterfallHook(["source", "chunk", "hash"]), - /** @type {SyncWaterfallHook} */ - startup: new SyncWaterfallHook(["source", "chunk", "hash"]), + /** @type {SyncWaterfallHook} */ + startup: new SyncWaterfallHook(["source", "renderContext"]), + /** @type {SyncWaterfallHook} */ render: new SyncWaterfallHook([ "source", - "chunk", - "hash", "moduleTemplate", - "dependencyTemplates" + "renderContext" ]), renderWithEntry: new SyncWaterfallHook(["source", "chunk", "hash"]), moduleRequire: new SyncWaterfallHook([ @@ -107,12 +112,11 @@ module.exports = class MainTemplate { "hash", "moduleIdExpression" ]), + /** @type {SyncWaterfallHook} */ addModule: new SyncWaterfallHook([ "source", - "chunk", - "hash", - "moduleIdExpression", - "moduleExpression" + "expressions", + "renderContext" ]), currentHash: new SyncWaterfallHook(["source", "requestedLength"]), assetPath: new SyncWaterfallHook(["path", "options"]), @@ -125,24 +129,33 @@ module.exports = class MainTemplate { // It's weird here hotBootstrap: new SyncWaterfallHook(["source", "chunk", "hash"]) }); - this.hooks.startup.tap("MainTemplate", (source, chunk, hash) => { - /** @type {string[]} */ - const buf = []; - if (chunk.entryModule) { - buf.push("// Load entry module and return exports"); - buf.push( - `return ${this.renderRequireFunctionForModule( - hash, - chunk, - JSON.stringify(chunk.entryModule.id) - )}(${this.requireFn}.s = ${JSON.stringify(chunk.entryModule.id)});` - ); + this.hooks.startup.tap( + "MainTemplate", + (source, { chunk, hash, chunkGraph }) => { + /** @type {string[]} */ + const buf = []; + if (chunkGraph.getNumberOfEntryModules(chunk) > 0) { + buf.push("// Load entry module and return exports"); + let i = chunkGraph.getNumberOfEntryModules(chunk); + for (const entryModule of chunkGraph.getChunkEntryModulesIterable( + chunk + )) { + const mayReturn = --i === 0 ? "return " : ""; + buf.push( + `${mayReturn}${this.renderRequireFunctionForModule( + hash, + chunk, + JSON.stringify(entryModule.id) + )}(${this.requireFn}.s = ${JSON.stringify(entryModule.id)});` + ); + } + } + return Template.asString(buf); } - return Template.asString(buf); - }); + ); this.hooks.render.tap( "MainTemplate", - (bootstrapSource, chunk, hash, moduleTemplate, dependencyTemplates) => { + (bootstrapSource, moduleTemplate, renderContext) => { const source = new ConcatSource(); source.add("/******/ (function(modules) { // webpackBootstrap\n"); source.add(new PrefixSource("/******/", bootstrapSource)); @@ -154,10 +167,8 @@ module.exports = class MainTemplate { source.add( this.hooks.modules.call( new RawSource(""), - chunk, - hash, moduleTemplate, - dependencyTemplates + renderContext ) ); source.add(")"); @@ -171,7 +182,8 @@ module.exports = class MainTemplate { "var installedModules = {};" ]); }); - this.hooks.require.tap("MainTemplate", (source, chunk, hash) => { + this.hooks.require.tap("MainTemplate", (source, renderContext) => { + const { chunk, hash } = renderContext; return Template.asString([ source, "// Check if module is in cache", @@ -180,7 +192,9 @@ module.exports = class MainTemplate { "}", "// Create a new module (and put it into the cache)", "var module = installedModules[moduleId] = {", - Template.indent(this.hooks.moduleObj.call("", chunk, hash, "moduleId")), + Template.indent( + this.hooks.moduleObj.call("", "moduleId", renderContext) + ), "};", "", Template.asString( @@ -220,124 +234,125 @@ module.exports = class MainTemplate { "return module.exports;" ]); }); - this.hooks.moduleObj.tap( + this.hooks.moduleObj.tap("MainTemplate", () => { + return Template.asString(["i: moduleId,", "l: false,", "exports: {}"]); + }); + this.hooks.requireExtensions.tap( "MainTemplate", - (source, chunk, hash, varModuleId) => { - return Template.asString(["i: moduleId,", "l: false,", "exports: {}"]); + (source, renderContext) => { + const { chunk, hash } = renderContext; + const buf = []; + const chunkMaps = chunk.getChunkMaps(); + // Check if there are non initial chunks which need to be imported using require-ensure + if (Object.keys(chunkMaps.hash).length) { + buf.push("// This file contains only the entry chunk."); + buf.push("// The chunk loading function for additional chunks"); + buf.push(`${this.requireFn}.e = function requireEnsure(chunkId) {`); + buf.push(Template.indent("var promises = [];")); + buf.push( + Template.indent( + this.hooks.requireEnsure.call("", "chunkId", renderContext) + ) + ); + buf.push(Template.indent("return Promise.all(promises);")); + buf.push("};"); + } + buf.push(""); + buf.push("// expose the modules object (__webpack_modules__)"); + buf.push(`${this.requireFn}.m = modules;`); + + buf.push(""); + buf.push("// expose the module cache"); + buf.push(`${this.requireFn}.c = installedModules;`); + + buf.push(""); + buf.push("// define getter function for harmony exports"); + buf.push(`${this.requireFn}.d = function(exports, name, getter) {`); + buf.push( + Template.indent([ + `if(!${this.requireFn}.o(exports, name)) {`, + Template.indent([ + "Object.defineProperty(exports, name, { enumerable: true, get: getter });" + ]), + "}" + ]) + ); + buf.push("};"); + + buf.push(""); + buf.push("// define __esModule on exports"); + buf.push(`${this.requireFn}.r = function(exports) {`); + buf.push( + Template.indent([ + "if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {", + Template.indent([ + "Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });" + ]), + "}", + "Object.defineProperty(exports, '__esModule', { value: true });" + ]) + ); + buf.push("};"); + + buf.push(""); + buf.push("// create a fake namespace object"); + buf.push("// mode & 1: value is a module id, require it"); + buf.push("// mode & 2: merge all properties of value into the ns"); + buf.push("// mode & 4: return value when already ns object"); + buf.push("// mode & 8|1: behave like require"); + buf.push(`${this.requireFn}.t = function(value, mode) {`); + buf.push( + Template.indent([ + `if(mode & 1) value = ${this.requireFn}(value);`, + `if(mode & 8) return value;`, + "if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;", + "var ns = Object.create(null);", + `${this.requireFn}.r(ns);`, + "Object.defineProperty(ns, 'default', { enumerable: true, value: value });", + "if(mode & 2 && typeof value != 'string') for(var key in value) " + + `${this.requireFn}.d(ns, key, function(key) { ` + + "return value[key]; " + + "}.bind(null, key));", + "return ns;" + ]) + ); + buf.push("};"); + + buf.push(""); + buf.push( + "// getDefaultExport function for compatibility with non-harmony modules" + ); + buf.push(this.requireFn + ".n = function(module) {"); + buf.push( + Template.indent([ + "var getter = module && module.__esModule ?", + Template.indent([ + "function getDefault() { return module['default']; } :", + "function getModuleExports() { return module; };" + ]), + `${this.requireFn}.d(getter, 'a', getter);`, + "return getter;" + ]) + ); + buf.push("};"); + + buf.push(""); + buf.push("// Object.prototype.hasOwnProperty.call"); + buf.push( + `${ + this.requireFn + }.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };` + ); + + const publicPath = this.getPublicPath({ + hash: hash + }); + buf.push(""); + buf.push("// __webpack_public_path__"); + buf.push(`${this.requireFn}.p = ${JSON.stringify(publicPath)};`); + return Template.asString(buf); } ); - this.hooks.requireExtensions.tap("MainTemplate", (source, chunk, hash) => { - const buf = []; - const chunkMaps = chunk.getChunkMaps(); - // Check if there are non initial chunks which need to be imported using require-ensure - if (Object.keys(chunkMaps.hash).length) { - buf.push("// This file contains only the entry chunk."); - buf.push("// The chunk loading function for additional chunks"); - buf.push(`${this.requireFn}.e = function requireEnsure(chunkId) {`); - buf.push(Template.indent("var promises = [];")); - buf.push( - Template.indent( - this.hooks.requireEnsure.call("", chunk, hash, "chunkId") - ) - ); - buf.push(Template.indent("return Promise.all(promises);")); - buf.push("};"); - } - buf.push(""); - buf.push("// expose the modules object (__webpack_modules__)"); - buf.push(`${this.requireFn}.m = modules;`); - - buf.push(""); - buf.push("// expose the module cache"); - buf.push(`${this.requireFn}.c = installedModules;`); - - buf.push(""); - buf.push("// define getter function for harmony exports"); - buf.push(`${this.requireFn}.d = function(exports, name, getter) {`); - buf.push( - Template.indent([ - `if(!${this.requireFn}.o(exports, name)) {`, - Template.indent([ - "Object.defineProperty(exports, name, { enumerable: true, get: getter });" - ]), - "}" - ]) - ); - buf.push("};"); - - buf.push(""); - buf.push("// define __esModule on exports"); - buf.push(`${this.requireFn}.r = function(exports) {`); - buf.push( - Template.indent([ - "if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {", - Template.indent([ - "Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });" - ]), - "}", - "Object.defineProperty(exports, '__esModule', { value: true });" - ]) - ); - buf.push("};"); - - buf.push(""); - buf.push("// create a fake namespace object"); - buf.push("// mode & 1: value is a module id, require it"); - buf.push("// mode & 2: merge all properties of value into the ns"); - buf.push("// mode & 4: return value when already ns object"); - buf.push("// mode & 8|1: behave like require"); - buf.push(`${this.requireFn}.t = function(value, mode) {`); - buf.push( - Template.indent([ - `if(mode & 1) value = ${this.requireFn}(value);`, - `if(mode & 8) return value;`, - "if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;", - "var ns = Object.create(null);", - `${this.requireFn}.r(ns);`, - "Object.defineProperty(ns, 'default', { enumerable: true, value: value });", - "if(mode & 2 && typeof value != 'string') for(var key in value) " + - `${this.requireFn}.d(ns, key, function(key) { ` + - "return value[key]; " + - "}.bind(null, key));", - "return ns;" - ]) - ); - buf.push("};"); - - buf.push(""); - buf.push( - "// getDefaultExport function for compatibility with non-harmony modules" - ); - buf.push(this.requireFn + ".n = function(module) {"); - buf.push( - Template.indent([ - "var getter = module && module.__esModule ?", - Template.indent([ - "function getDefault() { return module['default']; } :", - "function getModuleExports() { return module; };" - ]), - `${this.requireFn}.d(getter, 'a', getter);`, - "return getter;" - ]) - ); - buf.push("};"); - - buf.push(""); - buf.push("// Object.prototype.hasOwnProperty.call"); - buf.push( - `${ - this.requireFn - }.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };` - ); - - const publicPath = this.getPublicPath({ - hash: hash - }); - buf.push(""); - buf.push("// __webpack_public_path__"); - buf.push(`${this.requireFn}.p = ${JSON.stringify(publicPath)};`); - return Template.asString(buf); - }); this.requireFn = "__webpack_require__"; } @@ -345,7 +360,7 @@ module.exports = class MainTemplate { /** * * @param {RenderManifestOptions} options render manifest options - * @returns {TODO[]} returns render manifest + * @returns {RenderManifestEntry[]} returns render manifest */ getRenderManifest(options) { const result = []; @@ -356,48 +371,36 @@ module.exports = class MainTemplate { } /** - * - * @param {string} hash hash to be used for render call - * @param {Chunk} chunk Chunk instance * @param {ModuleTemplate} moduleTemplate ModuleTemplate instance for render - * @param {DependencyTemplates} dependencyTemplates dependency templates + * @param {MainRenderContext} renderContext options object * @returns {ConcatSource} the newly generated source from rendering */ - render(hash, chunk, moduleTemplate, dependencyTemplates) { + render(moduleTemplate, renderContext) { + const { hash, chunk, chunkGraph } = renderContext; const buf = []; - buf.push( - this.hooks.bootstrap.call( - "", - chunk, - hash, - moduleTemplate, - dependencyTemplates - ) - ); + buf.push(this.hooks.bootstrap.call("", moduleTemplate, renderContext)); buf.push(this.hooks.localVars.call("", chunk, hash)); buf.push(""); buf.push("// The require function"); buf.push(`function ${this.requireFn}(moduleId) {`); - buf.push(Template.indent(this.hooks.require.call("", chunk, hash))); + buf.push(Template.indent(this.hooks.require.call("", renderContext))); buf.push("}"); buf.push(""); buf.push( - Template.asString(this.hooks.requireExtensions.call("", chunk, hash)) + Template.asString(this.hooks.requireExtensions.call("", renderContext)) ); buf.push(""); buf.push(Template.asString(this.hooks.beforeStartup.call("", chunk, hash))); - buf.push(Template.asString(this.hooks.startup.call("", chunk, hash))); + buf.push(Template.asString(this.hooks.startup.call("", renderContext))); let source = this.hooks.render.call( new OriginalSource( Template.prefix(buf, " \t") + "\n", "webpack/bootstrap" ), - chunk, - hash, moduleTemplate, - dependencyTemplates + renderContext ); - if (chunk.hasEntryModule()) { + if (chunkGraph.getNumberOfEntryModules(chunk) > 0) { source = this.hooks.renderWithEntry.call(source, chunk, hash); } if (!source) { @@ -427,19 +430,19 @@ module.exports = class MainTemplate { /** * - * @param {string} hash hash for render add fn - * @param {Chunk} chunk Chunk instance for require add fn - * @param {(string|number)=} varModuleId module id - * @param {Module} varModule Module instance + * @param {string} varModuleId module id + * @param {string} varModule Module instance + * @param {MainRenderContext} renderContext the render context * @returns {TODO} renderAddModule call */ - renderAddModule(hash, chunk, varModuleId, varModule) { + renderAddModule(varModuleId, varModule, renderContext) { return this.hooks.addModule.call( `modules[${varModuleId}] = ${varModule};`, - chunk, - hash, - varModuleId, - varModule + { + moduleId: varModuleId, + module: varModule + }, + renderContext ); } diff --git a/lib/Module.js b/lib/Module.js index 2d3df8b2b..fed565d43 100644 --- a/lib/Module.js +++ b/lib/Module.js @@ -477,9 +477,10 @@ class Module extends DependenciesBlock { /** * @param {Chunk} chunk the chunk which condition should be checked + * @param {Compilation} compilation the compilation * @returns {boolean} true, if the chunk is ok for the module */ - chunkCondition(chunk) { + chunkCondition(chunk, compilation) { return true; } diff --git a/lib/MultiEntryPlugin.js b/lib/MultiEntryPlugin.js deleted file mode 100644 index c88d1e04b..000000000 --- a/lib/MultiEntryPlugin.js +++ /dev/null @@ -1,79 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ - -"use strict"; - -const MultiModuleFactory = require("./MultiModuleFactory"); -const MultiEntryDependency = require("./dependencies/MultiEntryDependency"); -const SingleEntryDependency = require("./dependencies/SingleEntryDependency"); - -/** @typedef {import("./Compiler")} Compiler */ - -class MultiEntryPlugin { - /** - * The MultiEntryPlugin is invoked whenever this.options.entry value is an array of paths - * @param {string} context context path - * @param {string[]} entries array of entry paths - * @param {string} name entry key name - */ - constructor(context, entries, name) { - this.context = context; - this.entries = entries; - this.name = name; - } - - /** - * @param {Compiler} compiler the compiler instance - * @returns {void} - */ - apply(compiler) { - compiler.hooks.compilation.tap( - "MultiEntryPlugin", - (compilation, { normalModuleFactory }) => { - compilation.dependencyFactories.set( - MultiEntryDependency, - new MultiModuleFactory() - ); - compilation.dependencyFactories.set( - SingleEntryDependency, - normalModuleFactory - ); - } - ); - - compiler.hooks.make.tapAsync( - "MultiEntryPlugin", - (compilation, callback) => { - const { context, entries, name } = this; - - const dep = MultiEntryPlugin.createDependency(entries, name); - compilation.addEntry(context, dep, name, callback); - } - ); - } - - /** - * @param {string[]} entries each entry path string - * @param {string} name name of the entry - * @returns {MultiEntryDependency} returns a constructed Dependency - */ - static createDependency(entries, name) { - return new MultiEntryDependency( - entries.map((e, idx) => { - const dep = new SingleEntryDependency(e); - // Because entrypoints are not dependencies found in an - // existing module, we give it a synthetic id - dep.loc = { - name, - index: idx - }; - return dep; - }), - name - ); - } -} - -module.exports = MultiEntryPlugin; diff --git a/lib/MultiModule.js b/lib/MultiModule.js deleted file mode 100644 index 6529e3306..000000000 --- a/lib/MultiModule.js +++ /dev/null @@ -1,122 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ - -"use strict"; - -const { RawSource } = require("webpack-sources"); -const Module = require("./Module"); - -/** @typedef {import("webpack-sources").Source} Source */ -/** @typedef {import("./Compilation")} Compilation */ -/** @typedef {import("./DependencyTemplates")} DependencyTemplates */ -/** @typedef {import("./Module").SourceContext} SourceContext */ -/** @typedef {import("./RequestShortener")} RequestShortener */ -/** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */ -/** @typedef {import("./util/createHash").Hash} Hash */ - -class MultiModule extends Module { - constructor(context, dependencies, name) { - super("javascript/dynamic", context); - - // Info from Factory - this.dependencies = dependencies; - this.name = name; - this._identifier = `multi ${this.dependencies - .map(d => d.request) - .join(" ")}`; - } - - /** - * @returns {string} a unique identifier of the module - */ - identifier() { - return this._identifier; - } - - /** - * @param {RequestShortener} requestShortener the request shortener - * @returns {string} a user readable identifier of the module - */ - readableIdentifier(requestShortener) { - return `multi ${this.dependencies - .map(d => requestShortener.shorten(d.request)) - .join(" ")}`; - } - - /** - * @param {TODO} options TODO - * @param {Compilation} compilation the compilation - * @param {TODO} resolver TODO - * @param {TODO} fs the file system - * @param {function(Error=): void} callback callback function - * @returns {void} - */ - build(options, compilation, resolver, fs, callback) { - this.built = true; - this.buildMeta = {}; - this.buildInfo = {}; - return callback(); - } - - /** - * @param {TODO} fileTimestamps timestamps of files - * @param {TODO} contextTimestamps timestamps of directories - * @returns {boolean} true, if the module needs a rebuild - */ - needRebuild(fileTimestamps, contextTimestamps) { - return false; - } - - /** - * @returns {number} the estimated size of the module - */ - size() { - return 16 + this.dependencies.length * 12; - } - - /** - * @param {Hash} hash the hash used to track dependencies - * @param {Compilation} compilation the compilation - * @returns {void} - */ - updateHash(hash, compilation) { - hash.update("multi module"); - hash.update(this.name || ""); - super.updateHash(hash, compilation); - } - - /** - * @param {SourceContext} sourceContext source context - * @returns {Source} generated source - */ - source({ runtimeTemplate, moduleGraph }) { - const str = []; - let idx = 0; - for (const dep of this.dependencies) { - if (moduleGraph.getModule(dep)) { - if (idx === this.dependencies.length - 1) { - str.push("module.exports = "); - } - str.push( - runtimeTemplate.moduleRaw({ - module: moduleGraph.getModule(dep), - request: dep.request - }) - ); - } else { - str.push( - runtimeTemplate.missingModule({ - request: dep.request - }) - ); - } - str.push(";\n"); - idx++; - } - return new RawSource(str.join("")); - } -} - -module.exports = MultiModule; diff --git a/lib/MultiModuleFactory.js b/lib/MultiModuleFactory.js deleted file mode 100644 index 7025cd7f9..000000000 --- a/lib/MultiModuleFactory.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ - -"use strict"; - -const MultiModule = require("./MultiModule"); - -module.exports = class MultiModuleFactory { - constructor() { - this.hooks = Object.freeze({}); - } - - create(data, callback) { - const dependency = data.dependencies[0]; - callback( - null, - new MultiModule(data.context, dependency.dependencies, dependency.name) - ); - } -}; diff --git a/lib/Template.js b/lib/Template.js index 93300129d..7670fc117 100644 --- a/lib/Template.js +++ b/lib/Template.js @@ -11,6 +11,7 @@ const HotUpdateChunk = require("./HotUpdateChunk"); /** @typedef {import("webpack-sources").ConcatSource} ConcatSource */ /** @typedef {import("webpack-sources").Source} Source */ /** @typedef {import("./Chunk")} Chunk */ +/** @typedef {import("./ChunkGraph")} ChunkGraph */ /** @typedef {import("./DependencyTemplates")} DependencyTemplates */ /** @typedef {import("./Module")} Module */ /** @typedef {import("./ModuleGraph")} ModuleGraph */ @@ -30,6 +31,28 @@ const COMMENT_END_REGEX = /\*\//g; const PATH_NAME_NORMALIZE_REPLACE_REGEX = /[^a-zA-Z0-9_!§$()=\-^°]+/g; const MATCH_PADDED_HYPHENS_REPLACE_REGEX = /^-|-$/g; +/** + * @typedef {Object} RenderManifestOptions + * @property {Chunk} chunk the chunk used to render + * @property {string} hash + * @property {string} fullHash + * @property {TODO} outputOptions + * @property {{javascript: ModuleTemplate, webassembly: ModuleTemplate}} moduleTemplates + * @property {DependencyTemplates} dependencyTemplates + * @property {RuntimeTemplate} runtimeTemplate + * @property {ModuleGraph} moduleGraph + * @property {ChunkGraph} chunkGraph + */ + +/** + * @typedef {Object} RenderManifestEntry + * @property {function(): Source} render + * @property {string=} filenameTemplate + * @property {TODO=} pathOptions + * @property {TODO} identifier + * @property {TODO=} hash + */ + /** * @typedef {Object} HasId * @property {number | string} id diff --git a/lib/dependencies/SingleEntryDependency.js b/lib/dependencies/EntryDependency.js similarity index 71% rename from lib/dependencies/SingleEntryDependency.js rename to lib/dependencies/EntryDependency.js index 66d2a4619..1624dc73f 100644 --- a/lib/dependencies/SingleEntryDependency.js +++ b/lib/dependencies/EntryDependency.js @@ -7,7 +7,7 @@ const ModuleDependency = require("./ModuleDependency"); -class SingleEntryDependency extends ModuleDependency { +class EntryDependency extends ModuleDependency { /** * @param {string} request request path for entry */ @@ -16,8 +16,8 @@ class SingleEntryDependency extends ModuleDependency { } get type() { - return "single entry"; + return "entry"; } } -module.exports = SingleEntryDependency; +module.exports = EntryDependency; diff --git a/lib/dependencies/MultiEntryDependency.js b/lib/dependencies/MultiEntryDependency.js deleted file mode 100644 index b1293b2d2..000000000 --- a/lib/dependencies/MultiEntryDependency.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ - -"use strict"; - -const Dependency = require("../Dependency"); - -/** @typedef {import("./SingleEntryDependency")} SingleEntryDependency */ - -class MultiEntryDependency extends Dependency { - /** - * @param {SingleEntryDependency[]} dependencies an array of SingleEntryDependencies - * @param {string} name entry name - */ - constructor(dependencies, name) { - super(); - this.dependencies = dependencies; - this.name = name; - } - - get type() { - return "multi entry"; - } -} - -module.exports = MultiEntryDependency; diff --git a/lib/node/NodeMainTemplatePlugin.js b/lib/node/NodeMainTemplatePlugin.js index 21bed968f..6ea8ac308 100644 --- a/lib/node/NodeMainTemplatePlugin.js +++ b/lib/node/NodeMainTemplatePlugin.js @@ -7,11 +7,17 @@ const Template = require("../Template"); +/** @typedef {import("../MainTemplate")} MainTemplate */ + module.exports = class NodeMainTemplatePlugin { constructor(asyncChunkLoading) { this.asyncChunkLoading = asyncChunkLoading; } + /** + * @param {MainTemplate} mainTemplate the main template + * @returns {void} + */ apply(mainTemplate) { const needChunkOnDemandLoadingCode = chunk => { for (const chunkGroup of chunk.groupsIterable) { @@ -41,7 +47,7 @@ module.exports = class NodeMainTemplatePlugin { ); mainTemplate.hooks.requireExtensions.tap( "NodeMainTemplatePlugin", - (source, chunk) => { + (source, { chunk }) => { if (needChunkOnDemandLoadingCode(chunk)) { return Template.asString([ source, @@ -63,7 +69,9 @@ module.exports = class NodeMainTemplatePlugin { ); mainTemplate.hooks.requireEnsure.tap( "NodeMainTemplatePlugin", - (source, chunk, hash) => { + (source, chunkIdExpression, renderContext) => { + // TODO use chunkIdExpression instead of hard-coded chunkId + const { chunk, hash } = renderContext; const chunkFilename = mainTemplate.outputOptions.chunkFilename; const chunkMaps = chunk.getChunkMaps(); const insertMoreModules = [ @@ -71,10 +79,9 @@ module.exports = class NodeMainTemplatePlugin { "for(var moduleId in moreModules) {", Template.indent( mainTemplate.renderAddModule( - hash, - chunk, "moduleId", - "moreModules[moduleId]" + "moreModules[moduleId]", + renderContext ) ), "}" diff --git a/lib/optimize/AggressiveSplittingPlugin.js b/lib/optimize/AggressiveSplittingPlugin.js index 28161a601..c8144d569 100644 --- a/lib/optimize/AggressiveSplittingPlugin.js +++ b/lib/optimize/AggressiveSplittingPlugin.js @@ -12,7 +12,9 @@ const { compareModulesById } = require("../util/comparators"); const identifierUtils = require("../util/identifier"); /** @typedef {import("../Chunk")} Chunk */ +/** @typedef {import("../ChunkGraph")} ChunkGraph */ /** @typedef {import("../Compiler")} Compiler */ +/** @typedef {import("../Module")} Module */ const moveModuleBetween = (chunkGraph, oldChunk, newChunk) => { return module => { @@ -21,9 +23,14 @@ const moveModuleBetween = (chunkGraph, oldChunk, newChunk) => { }; }; -const isNotAEntryModule = entryModule => { +/** + * @param {ChunkGraph} chunkGraph the chunk graph + * @param {Chunk} chunk the chunk + * @returns {function(Module): boolean} filter for entry module + */ +const isNotAEntryModule = (chunkGraph, chunk) => { return module => { - return entryModule !== module; + return !chunkGraph.isEntryModuleInChunk(module, chunk); }; }; @@ -217,7 +224,7 @@ class AggressiveSplittingPlugin { ) { const modules = chunkGraph .getChunkModules(chunk) - .filter(isNotAEntryModule(chunk.entryModule)) + .filter(isNotAEntryModule(chunkGraph, chunk)) .sort((a, b) => { const aIdentifer = a.identifier(); const bIdentifer = b.identifier(); diff --git a/lib/optimize/EnsureChunkConditionsPlugin.js b/lib/optimize/EnsureChunkConditionsPlugin.js index 67d44715e..7041154a4 100644 --- a/lib/optimize/EnsureChunkConditionsPlugin.js +++ b/lib/optimize/EnsureChunkConditionsPlugin.js @@ -19,7 +19,7 @@ class EnsureChunkConditionsPlugin { const chunkGroups = new Set(); for (const module of compilation.modules) { for (const chunk of chunkGraph.getModuleChunksIterable(module)) { - if (!module.chunkCondition(chunk)) { + if (!module.chunkCondition(chunk, compilation)) { sourceChunks.add(chunk); for (const group of chunk.groupsIterable) { chunkGroups.add(group); @@ -31,7 +31,7 @@ class EnsureChunkConditionsPlugin { chunkGroupLoop: for (const chunkGroup of chunkGroups) { // Can module be placed in a chunk of this group? for (const chunk of chunkGroup.chunks) { - if (module.chunkCondition(chunk)) { + if (module.chunkCondition(chunk, compilation)) { targetChunks.add(chunk); continue chunkGroupLoop; } diff --git a/lib/optimize/ModuleConcatenationPlugin.js b/lib/optimize/ModuleConcatenationPlugin.js index c3ba0932f..c4d2080e2 100644 --- a/lib/optimize/ModuleConcatenationPlugin.js +++ b/lib/optimize/ModuleConcatenationPlugin.js @@ -332,9 +332,6 @@ class ModuleConcatenationPlugin { .getOptimizationBailout(moduleGraph) .push(formatBailoutWarning(warning[0], warning[1])); } - const chunks = chunkGraph.getModuleChunks( - concatConfiguration.rootModule - ); for (const m of modules) { usedModules.add(m); // remove module from chunk @@ -348,12 +345,6 @@ class ModuleConcatenationPlugin { ); }); } - // add concatenated module to the chunks - for (const chunk of chunks) { - if (chunk.entryModule === concatConfiguration.rootModule) { - chunk.entryModule = newModule; - } - } // add concatenated module to the compilation compilation.modules.push(newModule); } @@ -464,14 +455,23 @@ class ModuleConcatenationPlugin { } class ConcatConfiguration { + /** + * + * @param {Module} rootModule the root module + * @param {ConcatConfiguration=} cloneFrom base config + */ constructor(rootModule, cloneFrom) { this.rootModule = rootModule; if (cloneFrom) { - this.modules = cloneFrom.modules.createChild(5); - this.warnings = cloneFrom.warnings.createChild(5); + /** @type {StackedSetMap} */ + this.modules = cloneFrom.modules.createChild(); + /** @type {StackedSetMap} */ + this.warnings = cloneFrom.warnings.createChild(); } else { + /** @type {StackedSetMap} */ this.modules = new StackedSetMap(); this.modules.add(rootModule); + /** @type {StackedSetMap} */ this.warnings = new StackedSetMap(); } } @@ -504,6 +504,9 @@ class ConcatConfiguration { ); } + /** + * @returns {Set} modules as set + */ getModules() { return this.modules.asSet(); } diff --git a/lib/optimize/OccurrenceModuleOrderPlugin.js b/lib/optimize/OccurrenceModuleOrderPlugin.js index 897a4115c..ff7b1e6ac 100644 --- a/lib/optimize/OccurrenceModuleOrderPlugin.js +++ b/lib/optimize/OccurrenceModuleOrderPlugin.js @@ -42,7 +42,7 @@ class OccurrenceOrderModuleIdsPlugin { let entry = 0; for (const c of chunkGraph.getModuleChunksIterable(m)) { if (c.canBeInitial()) initial++; - if (c.entryModule === m) entry++; + if (chunkGraph.isEntryModuleInChunk(m, c)) entry++; } initialChunkChunkMap.set(m, initial); entryCountMap.set(m, entry); diff --git a/lib/optimize/RemoveEmptyChunksPlugin.js b/lib/optimize/RemoveEmptyChunksPlugin.js index ef3985ca0..2838a74d2 100644 --- a/lib/optimize/RemoveEmptyChunksPlugin.js +++ b/lib/optimize/RemoveEmptyChunksPlugin.js @@ -26,7 +26,7 @@ class RemoveEmptyChunksPlugin { if ( chunkGraph.getNumberOfChunkModules(chunk) === 0 && !chunk.hasRuntime() && - !chunk.hasEntryModule() + chunkGraph.getNumberOfEntryModules(chunk) === 0 ) { compilation.chunkGraph.disconnectChunk(chunk); chunks.splice(i, 1); diff --git a/lib/optimize/SplitChunksPlugin.js b/lib/optimize/SplitChunksPlugin.js index f225f8afa..220278911 100644 --- a/lib/optimize/SplitChunksPlugin.js +++ b/lib/optimize/SplitChunksPlugin.js @@ -658,7 +658,7 @@ module.exports = class SplitChunksPlugin { item.modules.size ) continue; - if (chunk.hasEntryModule()) continue; + if (chunkGraph.getNumberOfEntryModules(chunk) > 0) continue; for (const module of item.modules) { if (!chunkGraph.isModuleInChunk(module, chunk)) continue outer; @@ -742,7 +742,7 @@ module.exports = class SplitChunksPlugin { if (entrypoint) { compilation.entrypoints.delete(chunkName); entrypoint.remove(); - newChunk.entryModule = undefined; + chunkGraph.disconnectEntries(newChunk); } } if (item.cacheGroup.filename) { @@ -759,7 +759,7 @@ module.exports = class SplitChunksPlugin { if (!isReused) { // Add all modules to the new chunk for (const module of item.modules) { - if (!module.chunkCondition(newChunk)) continue; + if (!module.chunkCondition(newChunk, compilation)) continue; // Add module to new chunk chunkGraph.connectChunkAndModule(newChunk, module); // Remove module from used chunks @@ -866,7 +866,7 @@ module.exports = class SplitChunksPlugin { newPart.chunkReason = chunk.chunkReason; // Add all modules to the new chunk for (const module of group.items) { - if (!module.chunkCondition(newPart)) continue; + if (!module.chunkCondition(newPart, compilation)) continue; // Add module to new chunk chunkGraph.connectChunkAndModule(newPart, module); // Remove module from used chunks diff --git a/lib/wasm/WasmMainTemplatePlugin.js b/lib/wasm/WasmMainTemplatePlugin.js index ce85776b7..a3c68feb9 100644 --- a/lib/wasm/WasmMainTemplatePlugin.js +++ b/lib/wasm/WasmMainTemplatePlugin.js @@ -223,7 +223,7 @@ class WasmMainTemplatePlugin { ); mainTemplate.hooks.requireEnsure.tap( "WasmMainTemplatePlugin", - (source, chunk, hash) => { + (source, chunkIdExpression, { chunk, hash }) => { const webassemblyModuleFilename = mainTemplate.outputOptions.webassemblyModuleFilename; @@ -272,7 +272,7 @@ class WasmMainTemplatePlugin { "", `var wasmModules = ${JSON.stringify( chunkModuleMaps.id - )}[chunkId] || [];`, + )}[${chunkIdExpression}] || [];`, "", "wasmModules.forEach(function(wasmModuleId) {", Template.indent([ @@ -351,7 +351,7 @@ class WasmMainTemplatePlugin { ); mainTemplate.hooks.requireExtensions.tap( "WasmMainTemplatePlugin", - (source, chunk) => { + (source, { chunk }) => { const chunkGraph = this.compilation.chunkGraph; if ( !chunkGraph.hasModuleInGraph(chunk, m => diff --git a/lib/web/JsonpChunkTemplatePlugin.js b/lib/web/JsonpChunkTemplatePlugin.js index 00de4308a..c80b4d487 100644 --- a/lib/web/JsonpChunkTemplatePlugin.js +++ b/lib/web/JsonpChunkTemplatePlugin.js @@ -6,20 +6,12 @@ "use strict"; const { ConcatSource } = require("webpack-sources"); +const getEntryInfo = require("./JsonpHelpers").getEntryInfo; +/** @typedef {import("../Chunk")} Chunk */ /** @typedef {import("../ChunkTemplate")} ChunkTemplate */ /** @typedef {import("../Compilation")} Compilation */ -const getEntryInfo = chunk => { - return [chunk.entryModule].filter(Boolean).map(m => - [m.id].concat( - Array.from(chunk.groupsIterable)[0] - .chunks.filter(c => c !== chunk) - .map(c => c.id) - ) - ); -}; - class JsonpChunkTemplatePlugin { /** * @param {Compilation} compilation the compilation @@ -48,7 +40,7 @@ class JsonpChunkTemplatePlugin { )}] || []).push([${JSON.stringify(chunk.ids)},` ); source.add(modules); - const entries = getEntryInfo(chunk); + const entries = getEntryInfo(chunkGraph, chunk); if (entries.length > 0) { source.add(`,${JSON.stringify(entries)}`); } else if (prefetchChunks && prefetchChunks.length) { @@ -72,7 +64,7 @@ class JsonpChunkTemplatePlugin { "JsonpChunkTemplatePlugin", (hash, chunk) => { const chunkGraph = this.compilation.chunkGraph; - hash.update(JSON.stringify(getEntryInfo(chunk))); + hash.update(JSON.stringify(getEntryInfo(chunkGraph, chunk))); hash.update( JSON.stringify(chunk.getChildIdsByOrders(chunkGraph).prefetch) || "" ); diff --git a/lib/web/JsonpHelpers.js b/lib/web/JsonpHelpers.js new file mode 100644 index 000000000..72eff4799 --- /dev/null +++ b/lib/web/JsonpHelpers.js @@ -0,0 +1,26 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ + +"use strict"; + +/** @typedef {import("../Chunk")} Chunk */ +/** @typedef {import("../ChunkGraph")} ChunkGraph */ +/** @typedef {(string|number)[]} EntryItem */ + +/** + * @param {ChunkGraph} chunkGraph the chunk graph + * @param {Chunk} chunk the chunk + * @returns {EntryItem[]} serialized entry info: + * inner arrays have this format [module id, ...chunk ids] + */ +exports.getEntryInfo = (chunkGraph, chunk) => { + return Array.from( + chunkGraph.getChunkEntryModulesWithChunkGroupIterable(chunk) + ).map(([module, chunkGroup]) => + [module.id].concat( + chunkGroup.chunks.filter(c => c !== chunk).map(c => c.id) + ) + ); +}; diff --git a/lib/web/JsonpMainTemplatePlugin.js b/lib/web/JsonpMainTemplatePlugin.js index 91c76750e..d48f0d540 100644 --- a/lib/web/JsonpMainTemplatePlugin.js +++ b/lib/web/JsonpMainTemplatePlugin.js @@ -8,8 +8,10 @@ const { SyncWaterfallHook } = require("tapable"); const MainTemplate = require("../MainTemplate"); const Template = require("../Template"); +const getEntryInfo = require("./JsonpHelpers").getEntryInfo; /** @typedef {import("../Compilation")} Compilation */ +/** @typedef {import("../MainTemplate")} MainTemplate */ const mainTemplateHooksMap = new WeakMap(); @@ -39,6 +41,10 @@ class JsonpMainTemplatePlugin { return hooks; } + /** + * @param {MainTemplate} mainTemplate the main template + * @returns {void} + */ apply(mainTemplate) { const needChunkOnDemandLoadingCode = chunk => { for (const chunkGroup of chunk.groupsIterable) { @@ -283,13 +289,13 @@ class JsonpMainTemplatePlugin { ); mainTemplate.hooks.requireEnsure.tap( "JsonpMainTemplatePlugin load", - (source, chunk, hash) => { + (source, chunkIdExpression, { chunk, hash }) => { return Template.asString([ source, "", "// JSONP chunk loading for javascript", "", - "var installedChunkData = installedChunks[chunkId];", + `var installedChunkData = installedChunks[${chunkIdExpression}];`, 'if(installedChunkData !== 0) { // 0 means "already installed".', Template.indent([ "", @@ -301,7 +307,7 @@ class JsonpMainTemplatePlugin { "// setup Promise in chunk cache", "var promise = new Promise(function(resolve, reject) {", Template.indent([ - "installedChunkData = installedChunks[chunkId] = [resolve, reject];" + `installedChunkData = installedChunks[${chunkIdExpression}] = [resolve, reject];` ]), "});", "promises.push(installedChunkData[2] = promise);", @@ -318,11 +324,12 @@ class JsonpMainTemplatePlugin { } ); mainTemplate.hooks.requireEnsure.tap( - { + // TODO typing are broken + /** @type {any} */ ({ name: "JsonpMainTemplatePlugin preload", stage: 10 - }, - (source, chunk, hash) => { + }), + (source, chunkIdExpression, { chunk, hash }) => { const chunkMap = chunk.getChildIdsByOrdersMap( this.compilation.chunkGraph ).preload; @@ -334,7 +341,7 @@ class JsonpMainTemplatePlugin { "", `var chunkPreloadMap = ${JSON.stringify(chunkMap, null, "\t")};`, "", - "var chunkPreloadData = chunkPreloadMap[chunkId];", + `var chunkPreloadData = chunkPreloadMap[${chunkIdExpression}];`, "if(chunkPreloadData) {", Template.indent([ "var head = document.getElementsByTagName('head')[0];", @@ -356,7 +363,7 @@ class JsonpMainTemplatePlugin { ); mainTemplate.hooks.requireExtensions.tap( "JsonpMainTemplatePlugin", - (source, chunk) => { + (source, { chunk }) => { if (!needChunkOnDemandLoadingCode(chunk)) return source; return Template.asString([ @@ -371,7 +378,8 @@ class JsonpMainTemplatePlugin { ); mainTemplate.hooks.bootstrap.tap( "JsonpMainTemplatePlugin", - (source, chunk, hash) => { + (source, moduleTemplate, renderContext) => { + const { chunk, hash } = renderContext; if (needChunkLoadingCode(chunk)) { const withDefer = needEntryDeferringCode(chunk); const withPrefetch = needPrefetchingCode(chunk); @@ -402,10 +410,9 @@ class JsonpMainTemplatePlugin { "if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {", Template.indent( mainTemplate.renderAddModule( - hash, - chunk, "moduleId", - "moreModules[moduleId]" + "moreModules[moduleId]", + renderContext ) ), "}" @@ -525,16 +532,10 @@ class JsonpMainTemplatePlugin { ); mainTemplate.hooks.startup.tap( "JsonpMainTemplatePlugin", - (source, chunk, hash) => { + (source, { chunk, chunkGraph }) => { if (needEntryDeferringCode(chunk)) { - if (chunk.hasEntryModule()) { - const entries = [chunk.entryModule].filter(Boolean).map(m => - [m.id].concat( - Array.from(chunk.groupsIterable)[0] - .chunks.filter(c => c !== chunk) - .map(c => c.id) - ) - ); + if (chunkGraph.getNumberOfEntryModules(chunk) > 0) { + const entries = getEntryInfo(chunkGraph, chunk); return Template.asString([ "// add entry module to deferred list", `deferredModules.push(${entries diff --git a/lib/webpack.js b/lib/webpack.js index 4781b784f..7a199ac73 100644 --- a/lib/webpack.js +++ b/lib/webpack.js @@ -94,6 +94,7 @@ exportPlugins(exports, { Dependency: () => require("./Dependency"), DllPlugin: () => require("./DllPlugin"), DllReferencePlugin: () => require("./DllReferencePlugin"), + EntryPlugin: () => require("./EntryPlugin"), EnvironmentPlugin: () => require("./EnvironmentPlugin"), EvalDevToolModulePlugin: () => require("./EvalDevToolModulePlugin"), EvalSourceMapDevToolPlugin: () => require("./EvalSourceMapDevToolPlugin"), @@ -117,7 +118,6 @@ exportPlugins(exports, { ProgressPlugin: () => require("./ProgressPlugin"), ProvidePlugin: () => require("./ProvidePlugin"), SetVarMainTemplatePlugin: () => require("./SetVarMainTemplatePlugin"), - SingleEntryPlugin: () => require("./SingleEntryPlugin"), SourceMapDevToolPlugin: () => require("./SourceMapDevToolPlugin"), Stats: () => require("./Stats"), Template: () => require("./Template"), diff --git a/lib/webworker/WebWorkerMainTemplatePlugin.js b/lib/webworker/WebWorkerMainTemplatePlugin.js index e0482c584..af814df4c 100644 --- a/lib/webworker/WebWorkerMainTemplatePlugin.js +++ b/lib/webworker/WebWorkerMainTemplatePlugin.js @@ -7,7 +7,13 @@ const Template = require("../Template"); +/** @typedef {import("../MainTemplate")} MainTemplate */ + class WebWorkerMainTemplatePlugin { + /** + * @param {MainTemplate} mainTemplate the main template + * @returns {void} + */ apply(mainTemplate) { const needChunkOnDemandLoadingCode = chunk => { for (const chunkGroup of chunk.groupsIterable) { @@ -36,7 +42,8 @@ class WebWorkerMainTemplatePlugin { ); mainTemplate.hooks.requireEnsure.tap( "WebWorkerMainTemplatePlugin", - (_, chunk, hash) => { + (_, chunkIdExpression, { chunk, hash }) => { + // TODO use chunkIdExpression instead of chunkId const chunkFilename = mainTemplate.outputOptions.chunkFilename; const chunkMaps = chunk.getChunkMaps(); return Template.asString([ @@ -106,7 +113,8 @@ class WebWorkerMainTemplatePlugin { ); mainTemplate.hooks.bootstrap.tap( "WebWorkerMainTemplatePlugin", - (source, chunk, hash) => { + (source, moduleTemplate, renderContext) => { + const { chunk } = renderContext; if (needChunkOnDemandLoadingCode(chunk)) { const chunkCallbackName = mainTemplate.outputOptions.chunkCallbackName; @@ -120,10 +128,9 @@ class WebWorkerMainTemplatePlugin { "for(var moduleId in moreModules) {", Template.indent( mainTemplate.renderAddModule( - hash, - chunk, "moduleId", - "moreModules[moduleId]" + "moreModules[moduleId]", + renderContext ) ), "}", diff --git a/test/StatsTestCases.test.js b/test/StatsTestCases.test.js index ad4bc1a39..bb2bc092e 100644 --- a/test/StatsTestCases.test.js +++ b/test/StatsTestCases.test.js @@ -68,6 +68,20 @@ describe("StatsTestCases", () => { ]) ); }; + c.hooks.compilation.tap("StatsTestCasesTest", compilation => { + [ + "optimize", + "optimizeModulesBasic", + "optimizeChunksBasic", + "afterOptimizeTree", + "afterOptimizeAssets", + "beforeHash" + ].forEach(hook => { + compilation.hooks[hook].tap("TestCasesTest", () => + compilation.checkConstraints() + ); + }); + }); }); c.run((err, stats) => { if (err) return done(err); diff --git a/test/__snapshots__/StatsTestCases.test.js.snap b/test/__snapshots__/StatsTestCases.test.js.snap index c4b4cbb48..48b075c12 100644 --- a/test/__snapshots__/StatsTestCases.test.js.snap +++ b/test/__snapshots__/StatsTestCases.test.js.snap @@ -1,17 +1,17 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`StatsTestCases should print correct stats for aggressive-splitting-entry 1`] = ` -"Hash: 44a278e3b0741b9b5da644a278e3b0741b9b5da6 +"Hash: 5071403fab92cdd591e25071403fab92cdd591e2 Child fitting: - Hash: 44a278e3b0741b9b5da6 + Hash: 5071403fab92cdd591e2 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names d4b551c6319035df2898.js 1.05 KiB 0 [emitted] 7029d2a129d88406bdea.js 1.94 KiB 1 [emitted] - 9d3d08d313ade4d2c47a.js 11.1 KiB 2 [emitted] + ebed0abd0a2953a40be0.js 11.1 KiB 2 [emitted] 5d5aae6ca1af5d6e6ea4.js 1.94 KiB 3 [emitted] - Entrypoint main = 5d5aae6ca1af5d6e6ea4.js 7029d2a129d88406bdea.js 9d3d08d313ade4d2c47a.js + Entrypoint main = 5d5aae6ca1af5d6e6ea4.js 7029d2a129d88406bdea.js ebed0abd0a2953a40be0.js chunk {0} d4b551c6319035df2898.js 916 bytes <{1}> <{2}> <{3}> > ./g [4] ./index.js 7:0-13 [7] ./g.js 916 bytes {0} [built] @@ -19,7 +19,7 @@ Child fitting: > ./index main [1] ./c.js 899 bytes {1} [built] [2] ./d.js 899 bytes {1} [built] - chunk {2} 9d3d08d313ade4d2c47a.js 1.87 KiB ={1}= ={3}= >{0}< [entry] [rendered] + chunk {2} ebed0abd0a2953a40be0.js 1.87 KiB ={1}= ={3}= >{0}< [entry] [rendered] > ./index main [3] ./e.js 899 bytes {2} [built] [4] ./index.js 111 bytes {2} [built] @@ -29,15 +29,15 @@ Child fitting: [0] ./b.js 899 bytes {3} [built] [5] ./a.js 899 bytes {3} [built] Child content-change: - Hash: 44a278e3b0741b9b5da6 + Hash: 5071403fab92cdd591e2 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names d4b551c6319035df2898.js 1.05 KiB 0 [emitted] 7029d2a129d88406bdea.js 1.94 KiB 1 [emitted] - 9d3d08d313ade4d2c47a.js 11.1 KiB 2 [emitted] + ebed0abd0a2953a40be0.js 11.1 KiB 2 [emitted] 5d5aae6ca1af5d6e6ea4.js 1.94 KiB 3 [emitted] - Entrypoint main = 5d5aae6ca1af5d6e6ea4.js 7029d2a129d88406bdea.js 9d3d08d313ade4d2c47a.js + Entrypoint main = 5d5aae6ca1af5d6e6ea4.js 7029d2a129d88406bdea.js ebed0abd0a2953a40be0.js chunk {0} d4b551c6319035df2898.js 916 bytes <{1}> <{2}> <{3}> > ./g [4] ./index.js 7:0-13 [7] ./g.js 916 bytes {0} [built] @@ -45,7 +45,7 @@ Child content-change: > ./index main [1] ./c.js 899 bytes {1} [built] [2] ./d.js 899 bytes {1} [built] - chunk {2} 9d3d08d313ade4d2c47a.js 1.87 KiB ={1}= ={3}= >{0}< [entry] [rendered] + chunk {2} ebed0abd0a2953a40be0.js 1.87 KiB ={1}= ={3}= >{0}< [entry] [rendered] > ./index main [3] ./e.js 899 bytes {2} [built] [4] ./index.js 111 bytes {2} [built] @@ -57,7 +57,7 @@ Child content-change: `; exports[`StatsTestCases should print correct stats for aggressive-splitting-on-demand 1`] = ` -"Hash: 02a058acce1bfbcd9896 +"Hash: 9418f05bd974463160e9 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -71,9 +71,9 @@ c99c160aba2d9a94e5d1.js 1.94 KiB 5 [emitted] 6a8e74d82c35e3f013d2.js 1 KiB 7 [emitted] ee043b525cd899e33ec0.js 1.94 KiB 8 [emitted] 01a8254701931adbf278.js 1.01 KiB 9 [emitted] -57253719544987787b40.js 9.7 KiB 10 [emitted] main +9162e370d5b0e4d1fe70.js 9.7 KiB 10 [emitted] main ba9fedb7aa0c69201639.js 1.94 KiB 11 [emitted] -Entrypoint main = 57253719544987787b40.js +Entrypoint main = 9162e370d5b0e4d1fe70.js chunk {0} 2736cf9d79233cd0a9b6.js 1.76 KiB <{10}> ={2}= ={3}= ={4}= ={5}= ={7}= [recorded] aggressive splitted > ./b ./d ./e ./f ./g [11] ./index.js 5:0-44 > ./b ./d ./e ./f ./g ./h ./i ./j ./k [11] ./index.js 6:0-72 @@ -115,7 +115,7 @@ chunk {8} ee043b525cd899e33ec0.js 1.76 KiB <{10}> ={4}= [recorded] aggressive chunk {9} 01a8254701931adbf278.js 899 bytes <{10}> > ./a [11] ./index.js 1:0-16 [10] ./a.js 899 bytes {9} [built] -chunk {10} 57253719544987787b40.js (main) 248 bytes >{0}< >{1}< >{2}< >{3}< >{4}< >{5}< >{6}< >{7}< >{8}< >{9}< >{11}< [entry] [rendered] +chunk {10} 9162e370d5b0e4d1fe70.js (main) 248 bytes >{0}< >{1}< >{2}< >{3}< >{4}< >{5}< >{6}< >{7}< >{8}< >{9}< >{11}< [entry] [rendered] > ./index main [11] ./index.js 248 bytes {10} [built] chunk {11} ba9fedb7aa0c69201639.js 1.76 KiB <{10}> ={2}= ={6}= [rendered] [recorded] aggressive splitted @@ -467,7 +467,7 @@ Child all: `; exports[`StatsTestCases should print correct stats for chunk-module-id-range 1`] = ` -"Hash: 8683bda4416097d173ee +"Hash: 04aadacf6417d157d7a8 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -492,7 +492,7 @@ chunk {1} main1.js (main1) 136 bytes [entry] [rendered] `; exports[`StatsTestCases should print correct stats for chunks 1`] = ` -"Hash: bb90fc9e61205a066fee +"Hash: 9557124dd322802a4580 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -504,7 +504,7 @@ Entrypoint main = bundle.js chunk {0} bundle.js (main) 73 bytes >{1}< >{2}< [entry] [rendered] > ./index main [0] ./index.js 51 bytes {0} [built] - single entry ./index main + entry ./index main factory:Xms building:Xms = Xms [1] ./a.js 22 bytes {0} [built] cjs require ./a [0] ./index.js 1:0-14 @@ -530,7 +530,7 @@ chunk {3} 3.bundle.js 44 bytes <{2}> [rendered] `; exports[`StatsTestCases should print correct stats for chunks-development 1`] = ` -"Hash: 83bf92a94bc3834801e8 +"Hash: b66c6464f88d39a97070 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -564,7 +564,7 @@ chunk {main} bundle.js (main) 73 bytes >{0}< >{1}< [entry] [rendered] cjs require ./a [./index.js] 1:0-14 [./index.js] Xms -> factory:Xms building:Xms = Xms [./index.js] 51 bytes {main} [built] - single entry ./index main + entry ./index main factory:Xms building:Xms = Xms" `; @@ -581,7 +581,7 @@ chunk {3} 3.bundle.js (c) 98 bytes <{1}> <{2}> >{1}< >{2}< [rendered] `; exports[`StatsTestCases should print correct stats for color-disabled 1`] = ` -"Hash: c5ad40363e9aee54c089 +"Hash: 703cfa0463cb3c00055c Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -591,7 +591,7 @@ Entrypoint main = main.js `; exports[`StatsTestCases should print correct stats for color-enabled 1`] = ` -"Hash: c5ad40363e9aee54c089 +"Hash: 703cfa0463cb3c00055c Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -601,7 +601,7 @@ Entrypoint main = main.js `; exports[`StatsTestCases should print correct stats for color-enabled-custom 1`] = ` -"Hash: c5ad40363e9aee54c089 +"Hash: 703cfa0463cb3c00055c Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -611,7 +611,7 @@ Entrypoint main = main.js `; exports[`StatsTestCases should print correct stats for commons-chunk-min-size-0 1`] = ` -"Hash: 54d4e5458e5d48cb25ea +"Hash: 35dc5b4d12d551e4af91 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -628,7 +628,7 @@ Entrypoint entry-1 = vendor-1~entry-1.js entry-1.js `; exports[`StatsTestCases should print correct stats for commons-chunk-min-size-Infinity 1`] = ` -"Hash: 275af2436329c6c382a9 +"Hash: 5dd30065e34a02ecc6a8 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -645,9 +645,9 @@ Entrypoint entry-1 = vendor-1.js entry-1.js `; exports[`StatsTestCases should print correct stats for commons-plugin-issue-4980 1`] = ` -"Hash: 137d627ba070d33cdda49a001f783027b840be9c +"Hash: 35f4c0b458700e5690125d578fbbda31da1fdadb Child - Hash: 137d627ba070d33cdda4 + Hash: 35f4c0b458700e569012 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -660,7 +660,7 @@ Child | ./submodule-a.js 59 bytes [built] | ./submodule-b.js 59 bytes [built] Child - Hash: 9a001f783027b840be9c + Hash: 5d578fbbda31da1fdadb Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -692,9 +692,9 @@ exports[`StatsTestCases should print correct stats for concat-and-sideeffects 1` `; exports[`StatsTestCases should print correct stats for define-plugin 1`] = ` -"Hash: cfe08d4450db77f81610f4228fcb997ec81e2aa6bb43e7d151657ea2b793 +"Hash: d137985c3dc6e1d36484ae900f5ab7a1699250503bca3a1a2ed59b322b45 Child - Hash: cfe08d4450db77f81610 + Hash: d137985c3dc6e1d36484 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -702,7 +702,7 @@ Child Entrypoint main = main.js [0] ./index.js 24 bytes {0} [built] Child - Hash: f4228fcb997ec81e2aa6 + Hash: ae900f5ab7a169925050 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -710,7 +710,7 @@ Child Entrypoint main = main.js [0] ./index.js 24 bytes {0} [built] Child - Hash: bb43e7d151657ea2b793 + Hash: 3bca3a1a2ed59b322b45 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -720,7 +720,7 @@ Child `; exports[`StatsTestCases should print correct stats for dll-reference-plugin-issue-7624 1`] = ` -"Hash: 29b62432962bce4c54c0 +"Hash: b103d43f856eb3a1c997 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -730,7 +730,7 @@ Entrypoint main = bundle.js `; exports[`StatsTestCases should print correct stats for dll-reference-plugin-issue-7624-error 1`] = ` -"Hash: 701dcf62b26d0347b899 +"Hash: 4a2b1eec4a4806b9dc12 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -743,7 +743,7 @@ Unexpected end of JSON input while parsing near ''" `; exports[`StatsTestCases should print correct stats for exclude-with-loader 1`] = ` -"Hash: 52eadc5de721f000106b +"Hash: 83fac664b3322d053bd8 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -756,7 +756,7 @@ Entrypoint main = bundle.js `; exports[`StatsTestCases should print correct stats for external 1`] = ` -"Hash: 7a4bb5500ee0eddeee44 +"Hash: dbb8d2da46449d2bfe85 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -767,9 +767,9 @@ Entrypoint main = main.js `; exports[`StatsTestCases should print correct stats for filter-warnings 1`] = ` -"Hash: 0f57e2bad314fb37b8ed0f57e2bad314fb37b8ed0f57e2bad314fb37b8ed0f57e2bad314fb37b8ed0f57e2bad314fb37b8ed0f57e2bad314fb37b8ed0f57e2bad314fb37b8ed0f57e2bad314fb37b8ed0f57e2bad314fb37b8ed0f57e2bad314fb37b8ed0f57e2bad314fb37b8ed0f57e2bad314fb37b8ed0f57e2bad314fb37b8ed +"Hash: 88aed3fe1afcb496898d88aed3fe1afcb496898d88aed3fe1afcb496898d88aed3fe1afcb496898d88aed3fe1afcb496898d88aed3fe1afcb496898d88aed3fe1afcb496898d88aed3fe1afcb496898d88aed3fe1afcb496898d88aed3fe1afcb496898d88aed3fe1afcb496898d88aed3fe1afcb496898d88aed3fe1afcb496898d Child undefined: - Hash: 0f57e2bad314fb37b8ed + Hash: 88aed3fe1afcb496898d Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -798,49 +798,49 @@ Child undefined: WARNING in UglifyJs Plugin: Dropping unused function someRemoteUnUsedFunction5 [./a.js:7,0] in bundle.js Child UglifyJs: - Hash: 0f57e2bad314fb37b8ed + Hash: 88aed3fe1afcb496898d Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names bundle.js 2.84 KiB 0 [emitted] main Entrypoint main = bundle.js Child /UglifyJs/: - Hash: 0f57e2bad314fb37b8ed + Hash: 88aed3fe1afcb496898d Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names bundle.js 2.84 KiB 0 [emitted] main Entrypoint main = bundle.js Child warnings => true: - Hash: 0f57e2bad314fb37b8ed + Hash: 88aed3fe1afcb496898d Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names bundle.js 2.84 KiB 0 [emitted] main Entrypoint main = bundle.js Child [UglifyJs]: - Hash: 0f57e2bad314fb37b8ed + Hash: 88aed3fe1afcb496898d Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names bundle.js 2.84 KiB 0 [emitted] main Entrypoint main = bundle.js Child [/UglifyJs/]: - Hash: 0f57e2bad314fb37b8ed + Hash: 88aed3fe1afcb496898d Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names bundle.js 2.84 KiB 0 [emitted] main Entrypoint main = bundle.js Child [warnings => true]: - Hash: 0f57e2bad314fb37b8ed + Hash: 88aed3fe1afcb496898d Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names bundle.js 2.84 KiB 0 [emitted] main Entrypoint main = bundle.js Child should not filter: - Hash: 0f57e2bad314fb37b8ed + Hash: 88aed3fe1afcb496898d Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -869,7 +869,7 @@ Child should not filter: WARNING in UglifyJs Plugin: Dropping unused function someRemoteUnUsedFunction5 [./a.js:7,0] in bundle.js Child /should not filter/: - Hash: 0f57e2bad314fb37b8ed + Hash: 88aed3fe1afcb496898d Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -898,7 +898,7 @@ Child /should not filter/: WARNING in UglifyJs Plugin: Dropping unused function someRemoteUnUsedFunction5 [./a.js:7,0] in bundle.js Child warnings => false: - Hash: 0f57e2bad314fb37b8ed + Hash: 88aed3fe1afcb496898d Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -927,7 +927,7 @@ Child warnings => false: WARNING in UglifyJs Plugin: Dropping unused function someRemoteUnUsedFunction5 [./a.js:7,0] in bundle.js Child [should not filter]: - Hash: 0f57e2bad314fb37b8ed + Hash: 88aed3fe1afcb496898d Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -956,7 +956,7 @@ Child [should not filter]: WARNING in UglifyJs Plugin: Dropping unused function someRemoteUnUsedFunction5 [./a.js:7,0] in bundle.js Child [/should not filter/]: - Hash: 0f57e2bad314fb37b8ed + Hash: 88aed3fe1afcb496898d Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -985,7 +985,7 @@ Child [/should not filter/]: WARNING in UglifyJs Plugin: Dropping unused function someRemoteUnUsedFunction5 [./a.js:7,0] in bundle.js Child [warnings => false]: - Hash: 0f57e2bad314fb37b8ed + Hash: 88aed3fe1afcb496898d Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -1020,10 +1020,10 @@ exports[`StatsTestCases should print correct stats for graph-correctness-entries Entrypoint e2 = e2.js chunk {0} e1.js (e1) 49 bytes >{2}< [entry] [rendered] [0] ./e1.js 49 bytes {0} [built] - single entry ./e1 e1 + entry ./e1 e1 chunk {1} e2.js (e2) 49 bytes >{3}< [entry] [rendered] [1] ./e2.js 49 bytes {1} [built] - single entry ./e2 e2 + entry ./e2 e2 chunk {2} a.js (a) 49 bytes <{0}> <{3}> >{4}< [rendered] [2] ./module-a.js 49 bytes {2} [built] import() ./module-a [0] ./e1.js 1:0-47 @@ -1042,7 +1042,7 @@ exports[`StatsTestCases should print correct stats for graph-correctness-modules Entrypoint e2 = e2.js chunk {0} e1.js (e1) 119 bytes >{2}< >{3}< [entry] [rendered] [0] ./e1.js 70 bytes {0} [built] - single entry ./e1 e1 + entry ./e1 e1 [1] ./module-x.js 49 bytes {0} {1} [built] harmony side effect evaluation ./module-x [0] ./e1.js 1:0-20 harmony side effect evaluation ./module-x [2] ./e2.js 1:0-20 @@ -1053,7 +1053,7 @@ chunk {1} e2.js (e2) 119 bytes >{3}< >{4}< [entry] [rendered] harmony side effect evaluation ./module-x [2] ./e2.js 1:0-20 import() ./module-x [6] ./module-b.js 2:0-20 [2] ./e2.js 70 bytes {1} [built] - single entry ./e2 e2 + entry ./e2 e2 chunk {2} a.js (a) 49 bytes <{0}> <{4}> >{5}< [rendered] [3] ./module-a.js 49 bytes {2} [built] import() ./module-a [0] ./e1.js 2:0-47 @@ -1071,7 +1071,7 @@ chunk {5} b.js (b) 179 bytes <{2}> >{4}< [rendered] `; exports[`StatsTestCases should print correct stats for import-context-filter 1`] = ` -"Hash: 7ad77a3e9e3d661cd55e +"Hash: 00093e0065918fc6beca Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -1088,7 +1088,7 @@ Entrypoint entry = entry.js `; exports[`StatsTestCases should print correct stats for import-weak 1`] = ` -"Hash: a4a61ec24e06498a1f58 +"Hash: 020bd304e43a2b2f22bb Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -1123,49 +1123,49 @@ Compilation error while processing magic comment(-s): /* webpackPrefetch: true, `; exports[`StatsTestCases should print correct stats for issue-7577 1`] = ` -"Hash: 343642fcbd3799129ba3c304c0cf29920d9747260bd6e5e36b1ff9a17678 +"Hash: 85309305fa40259fb1ebc74e886ded34938c99afb793a0bac9d49c018eb7 Child - Hash: 343642fcbd3799129ba3 + Hash: 85309305fa40259fb1eb Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names a-all~main-0034bb84916bcade4cc7.js 154 bytes all~main [emitted] all~main - a-main-14ee9c594789bd77b887.js 108 bytes main [emitted] main + a-main-9407860001b0bf9acb00.js 108 bytes main [emitted] main a-runtime~main-aa303e56a90b4559481f.js 6.05 KiB runtime~main [emitted] runtime~main - Entrypoint main = a-runtime~main-aa303e56a90b4559481f.js a-all~main-0034bb84916bcade4cc7.js a-main-14ee9c594789bd77b887.js + Entrypoint main = a-runtime~main-aa303e56a90b4559481f.js a-all~main-0034bb84916bcade4cc7.js a-main-9407860001b0bf9acb00.js [0] ./a.js 18 bytes {all~main} [built] Child - Hash: c304c0cf29920d974726 + Hash: c74e886ded34938c99af Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names b-all~main-a293363005660974db22.js 459 bytes all~main [emitted] all~main - b-main-1dc1f5a633a7b6c2376f.js 123 bytes main [emitted] main + b-main-ad8a5f8b02d5a200d778.js 123 bytes main [emitted] main b-runtime~main-937400e6bee421a9af47.js 6.05 KiB runtime~main [emitted] runtime~main b-vendors~main-13c0fc262f08dee65613.js 172 bytes vendors~main [emitted] vendors~main - Entrypoint main = b-runtime~main-937400e6bee421a9af47.js b-vendors~main-13c0fc262f08dee65613.js b-all~main-a293363005660974db22.js b-main-1dc1f5a633a7b6c2376f.js + Entrypoint main = b-runtime~main-937400e6bee421a9af47.js b-vendors~main-13c0fc262f08dee65613.js b-all~main-a293363005660974db22.js b-main-ad8a5f8b02d5a200d778.js [0] ./b.js 17 bytes {all~main} [built] [1] ./node_modules/vendor.js 23 bytes {vendors~main} [built] Child - Hash: 0bd6e5e36b1ff9a17678 + Hash: b793a0bac9d49c018eb7 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names - c-main-5eaed336f1da9c475636.js 114 bytes main [emitted] main + c-main-395ed4acf6a1f211e7f1.js 114 bytes main [emitted] main c-0-598d23de6ad7df2ab6e4.js 153 bytes 0 [emitted] c-1-9039f4a1a11a97f28320.js 459 bytes 1 [emitted] c-all~main-166656d0ac46d1a19871.js 296 bytes all~main [emitted] all~main c-runtime~main-54fe8e7231733bcf484a.js 8.84 KiB runtime~main [emitted] runtime~main - Entrypoint main = c-runtime~main-54fe8e7231733bcf484a.js c-all~main-166656d0ac46d1a19871.js c-main-5eaed336f1da9c475636.js (prefetch: c-0-598d23de6ad7df2ab6e4.js c-1-9039f4a1a11a97f28320.js) + Entrypoint main = c-runtime~main-54fe8e7231733bcf484a.js c-all~main-166656d0ac46d1a19871.js c-main-395ed4acf6a1f211e7f1.js (prefetch: c-0-598d23de6ad7df2ab6e4.js c-1-9039f4a1a11a97f28320.js) [0] ./c.js 61 bytes {all~main} [built] [1] ./b.js 17 bytes {1} [built] [2] ./node_modules/vendor.js 23 bytes {0} [built]" `; exports[`StatsTestCases should print correct stats for limit-chunk-count-plugin 1`] = ` -"Hash: 3f682d19df3a78cc355bea647ea3fd883ece89243ab5b7fed36cc043302dfa02c84a4a470a27c245 +"Hash: 107c243d2f4948779db6faef5739a00d90343e7d46e1640f099b398451adcc962a224e99bbf022c3 Child 1 chunks: - Hash: 3f682d19df3a78cc355b + Hash: 107c243d2f4948779db6 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -1179,7 +1179,7 @@ Child 1 chunks: [4] ./d.js 22 bytes {0} [built] [5] ./e.js 22 bytes {0} [built] Child 2 chunks: - Hash: ea647ea3fd883ece8924 + Hash: faef5739a00d90343e7d Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -1195,7 +1195,7 @@ Child 2 chunks: [4] ./d.js 22 bytes {1} [built] [5] ./e.js 22 bytes {1} [built] Child 3 chunks: - Hash: 3ab5b7fed36cc043302d + Hash: 46e1640f099b398451ad Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -1213,7 +1213,7 @@ Child 3 chunks: [2] ./b.js 22 bytes {2} [built] [5] ./e.js 22 bytes {2} [built] Child 4 chunks: - Hash: fa02c84a4a470a27c245 + Hash: cc962a224e99bbf022c3 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -1235,7 +1235,7 @@ Child 4 chunks: `; exports[`StatsTestCases should print correct stats for max-modules 1`] = ` -"Hash: ce942cd1353f7d6fc01e +"Hash: e8b18f1cf5f95cf5a285 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -1265,7 +1265,7 @@ Entrypoint main = main.js `; exports[`StatsTestCases should print correct stats for max-modules-default 1`] = ` -"Hash: ce942cd1353f7d6fc01e +"Hash: e8b18f1cf5f95cf5a285 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -1290,7 +1290,7 @@ Entrypoint main = main.js `; exports[`StatsTestCases should print correct stats for module-assets 1`] = ` -"Hash: 0aa43ba74041bc65bc0a +"Hash: 8ae1dea4bce18528f657 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Entrypoint main = main.js @@ -1472,7 +1472,7 @@ Child `; exports[`StatsTestCases should print correct stats for named-chunks-plugin 1`] = ` -"Hash: 0c5756674e2dda021828 +"Hash: 65cd83ae5b2980359572 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -1486,7 +1486,7 @@ Entrypoint entry = vendor.js entry.js `; exports[`StatsTestCases should print correct stats for named-chunks-plugin-async 1`] = ` -"Hash: 8517d17cf111f52660cd +"Hash: 421934d6424eb810e1a8 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -1500,7 +1500,7 @@ Entrypoint entry = entry.js `; exports[`StatsTestCases should print correct stats for no-emit-on-errors-plugin-with-child-error 1`] = ` -"Hash: 6a246e5dec75240f30bf +"Hash: 0d1fa1c56ef4d2b16cdd Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -1522,7 +1522,7 @@ Child child: `; exports[`StatsTestCases should print correct stats for optimize-chunks 1`] = ` -"Hash: 1f0728f6992d48535826 +"Hash: 2c343cbbb1c034dcc13d Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -1593,9 +1593,9 @@ You may need an appropriate loader to handle this file type. `; exports[`StatsTestCases should print correct stats for performance-different-mode-and-target 1`] = ` -"Hash: b27a7019f90a13ead012bb84b396eb1e98365d94fb930f6aa3329ab03a278deb0030bfebe86abb37a1cddcae25eb52f3112b62c8b61bc84829d26b13ae06efe5f0099a11af36 +"Hash: 27afa870ea890dcb8d211cf632c77c707c36d94b810d87a0ecb3d46fb6472b646a1947dce27d2c2ca90600658140ce9be0af7e07124a239ee933822c55b9d2204250eb77a29a Child - Hash: b27a7019f90a13ead012 + Hash: 27afa870ea890dcb8d21 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -1618,7 +1618,7 @@ Child You can limit the size of your bundles by using import() or require.ensure to lazy load some parts of your application. For more info visit https://webpack.js.org/guides/code-splitting/ Child - Hash: bb84b396eb1e98365d94 + Hash: 1cf632c77c707c36d94b Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -1641,7 +1641,7 @@ Child You can limit the size of your bundles by using import() or require.ensure to lazy load some parts of your application. For more info visit https://webpack.js.org/guides/code-splitting/ Child - Hash: fb930f6aa3329ab03a27 + Hash: 810d87a0ecb3d46fb647 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -1649,7 +1649,7 @@ Child Entrypoint main = no-warning.pro-node.js [0] ./index.js 293 KiB {0} [built] Child - Hash: 8deb0030bfebe86abb37 + Hash: 2b646a1947dce27d2c2c Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -1657,7 +1657,7 @@ Child Entrypoint main = no-warning.dev-web.js [./index.js] 293 KiB {main} [built] Child - Hash: a1cddcae25eb52f3112b + Hash: a90600658140ce9be0af Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -1665,7 +1665,7 @@ Child Entrypoint main = no-warning.dev-node.js [./index.js] 293 KiB {main} [built] Child - Hash: 62c8b61bc84829d26b13 + Hash: 7e07124a239ee933822c Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -1673,7 +1673,7 @@ Child Entrypoint main [big] = no-warning.dev-web-with-limit-set.js [./index.js] 293 KiB {main} [built] Child - Hash: ae06efe5f0099a11af36 + Hash: 55b9d2204250eb77a29a Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -1874,7 +1874,7 @@ chunk {6} inner2.js (inner2) 0 bytes <{1}> [rendered]" `; exports[`StatsTestCases should print correct stats for preset-detailed 1`] = ` -"Hash: 437c9384ca68c9e15b6c +"Hash: 3b3a7ec8ed8bc5030c9b Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -1933,7 +1933,7 @@ exports[`StatsTestCases should print correct stats for preset-none-array 1`] = ` exports[`StatsTestCases should print correct stats for preset-none-error 1`] = `""`; exports[`StatsTestCases should print correct stats for preset-normal 1`] = ` -"Hash: 437c9384ca68c9e15b6c +"Hash: 3b3a7ec8ed8bc5030c9b Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -2011,7 +2011,7 @@ Entrypoints: `; exports[`StatsTestCases should print correct stats for preset-verbose 1`] = ` -"Hash: 437c9384ca68c9e15b6c +"Hash: 3b3a7ec8ed8bc5030c9b Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -2024,7 +2024,7 @@ chunk {0} main.js (main) 73 bytes >{1}< >{2}< [entry] [rendered] > ./index main [0] ./index.js 51 bytes {0} [depth 0] [built] ModuleConcatenation bailout: Module is not an ECMAScript module - single entry ./index main + entry ./index main factory:Xms building:Xms = Xms [1] ./a.js 22 bytes {0} [depth 1] [built] ModuleConcatenation bailout: Module is not an ECMAScript module @@ -2055,7 +2055,7 @@ chunk {3} 3.js 44 bytes <{2}> [rendered] `; exports[`StatsTestCases should print correct stats for resolve-plugin-context 1`] = ` -"Hash: 2e97eaab59275aaa8d93 +"Hash: 4ca4f81607549b34ea70 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -2069,7 +2069,7 @@ Entrypoint main = bundle.js `; exports[`StatsTestCases should print correct stats for reverse-sort-modules 1`] = ` -"Hash: ce942cd1353f7d6fc01e +"Hash: e8b18f1cf5f95cf5a285 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -2139,7 +2139,7 @@ Entrypoint e2 = runtime.js e2.js" `; exports[`StatsTestCases should print correct stats for scope-hoisting-bailouts 1`] = ` -"Hash: a0a30b6e8932d0227376 +"Hash: 6ceacb948e0119070c3d Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Entrypoint index = index.js @@ -2170,9 +2170,9 @@ Entrypoint entry = entry.js `; exports[`StatsTestCases should print correct stats for scope-hoisting-multi 1`] = ` -"Hash: d1e41fb7099e132879ee438a93ced10bfac3b362 +"Hash: e170f18d73c88b7b7d9ac46fd70f754a5383c1b7 Child - Hash: d1e41fb7099e132879ee + Hash: e170f18d73c88b7b7d9a Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Entrypoint first = vendor.js first.js @@ -2189,7 +2189,7 @@ Child [9] ./lazy_shared.js 31 bytes {5} [built] [10] ./lazy_second.js 55 bytes {4} [built] Child - Hash: 438a93ced10bfac3b362 + Hash: c46fd70f754a5383c1b7 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Entrypoint first = vendor.js first.js @@ -2219,7 +2219,7 @@ Child `; exports[`StatsTestCases should print correct stats for side-effects-issue-7428 1`] = ` -"Hash: 4f5d38944616c15bd399 +"Hash: 8f2bd5e4f61d541b2803 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -2242,7 +2242,7 @@ Entrypoint main = main.js [3] ./main.js + 1 modules 231 bytes {0} [built] harmony side effect evaluation ./CompB ./components/src/CompAB/index.js 2:0-43 harmony export imported specifier ./CompB ./components/src/CompAB/index.js 2:0-43 - single entry ./main.js main + entry ./main.js main | ./main.js 144 bytes [built] | ./components/src/CompAB/CompB.js 77 bytes [built] | [only some exports used: default] @@ -2267,7 +2267,7 @@ Entrypoint main = main.js `; exports[`StatsTestCases should print correct stats for side-effects-simple-unused 1`] = ` -"Hash: c7b680da5c0d869389e8 +"Hash: 2aad9ba482cb71fcd705 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -2276,7 +2276,7 @@ Entrypoint main = main.js [0] ./index.js + 2 modules 158 bytes {0} [built] harmony side effect evaluation ./c ./node_modules/pmodule/b.js 5:0-24 harmony export imported specifier ./c ./node_modules/pmodule/b.js 5:0-24 - single entry ./index main + entry ./index main | ./index.js 55 bytes [built] | ./node_modules/pmodule/index.js 75 bytes [built] | [only some exports used: default] @@ -2298,7 +2298,7 @@ Entrypoint main = main.js `; exports[`StatsTestCases should print correct stats for simple 1`] = ` -"Hash: 06cc914b885215f96c5a +"Hash: 0d863bcfaf259a5eba10 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -2308,14 +2308,14 @@ Entrypoint main = bundle.js `; exports[`StatsTestCases should print correct stats for simple-more-info 1`] = ` -"Hash: c8c226a954f967e61630 +"Hash: 64de01465a28fb4267d8 Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names bundle.js 3.57 KiB 0 [emitted] main Entrypoint main = bundle.js [0] ./index.js 0 bytes {0} [built] - single entry ./index main + entry ./index main factory:Xms building:Xms = Xms" `; @@ -2486,17 +2486,17 @@ Child manual: [6] ./c.js 72 bytes {3} {4} [built] chunk {5} default/a.js (a) 176 bytes ={7}= >{8}< [entry] [rendered] > ./a a - [1] ./d.js 20 bytes {1} {2} {3} {4} {5} {6} [built] - [10] ./a.js + 1 modules 156 bytes {5} {6} [built] - | ./a.js 121 bytes [built] - | ./e.js 20 bytes [built] + [1] ./d.js 20 bytes {1} {2} {3} {4} {5} {6} [built] + [9] ./a.js + 1 modules 156 bytes {5} {6} [built] + | ./a.js 121 bytes [built] + | ./e.js 20 bytes [built] chunk {6} default/async-a.js (async-a) 176 bytes <{0}> ={7}= >{8}< [rendered] > ./a [0] ./index.js 1:0-47 - [1] ./d.js 20 bytes {1} {2} {3} {4} {5} {6} [built] - [10] ./a.js + 1 modules 156 bytes {5} {6} [built] - | ./a.js 121 bytes [built] - | ./e.js 20 bytes [built] - chunk {7} default/vendors.js (vendors) 112 bytes <{0}> ={1}= ={2}= ={3}= ={4}= ={5}= ={6}= >{8}< [initial] [rendered] split chunk (cache group: vendors) (name: vendors) + [1] ./d.js 20 bytes {1} {2} {3} {4} {5} {6} [built] + [9] ./a.js + 1 modules 156 bytes {5} {6} [built] + | ./a.js 121 bytes [built] + | ./e.js 20 bytes [built] + chunk {7} default/vendors.js (vendors) 60 bytes <{0}> ={1}= ={2}= ={3}= ={4}= ={5}= ={6}= >{8}< [initial] [rendered] split chunk (cache group: vendors) (name: vendors) > ./a a > ./b b > ./c c @@ -2506,12 +2506,11 @@ Child manual: [2] ./node_modules/x.js 20 bytes {7} [built] [3] ./node_modules/y.js 20 bytes {7} [built] [7] ./node_modules/z.js 20 bytes {7} [built] - [8] multi x y z 52 bytes {7} [built] chunk {8} default/async-g.js (async-g) 54 bytes <{5}> <{6}> <{7}> [rendered] > ./g [] 6:0-47 > ./g [] 6:0-47 [5] ./f.js 20 bytes {1} {2} {3} {4} {8} [built] - [9] ./g.js 34 bytes {8} [built] + [8] ./g.js 34 bytes {8} [built] Child name-too-long: Entrypoint main = main.js Entrypoint aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = vendors~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa~async-a~async-b~async-c~bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb~cccccc~50ebc41f.js vendors~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa~async-a~async-b~bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.js aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa~async-a~async-b~async-c~bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb~cccccccccccccc~18066793.js async-a.js aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.js @@ -2656,12 +2655,12 @@ Child custom-chunks-filter-in-cache-groups: [0] ./index.js 147 bytes {0} [built] chunk {1} default/a.js (a) 216 bytes >{8}< [entry] [rendered] > ./a a - [1] ./d.js 20 bytes {1} {2} {3} {4} {5} {6} [built] - [2] ./node_modules/x.js 20 bytes {1} {7} [built] - [3] ./node_modules/y.js 20 bytes {1} {7} [built] - [10] ./a.js + 1 modules 156 bytes {1} {6} [built] - | ./a.js 121 bytes [built] - | ./e.js 20 bytes [built] + [1] ./d.js 20 bytes {1} {2} {3} {4} {5} {6} [built] + [2] ./node_modules/x.js 20 bytes {1} {7} [built] + [3] ./node_modules/y.js 20 bytes {1} {7} [built] + [9] ./a.js + 1 modules 156 bytes {1} {6} [built] + | ./a.js 121 bytes [built] + | ./e.js 20 bytes [built] chunk {2} default/b.js (b) 112 bytes ={7}= [entry] [rendered] > ./b b [1] ./d.js 20 bytes {1} {2} {3} {4} {5} {6} [built] @@ -2684,11 +2683,11 @@ Child custom-chunks-filter-in-cache-groups: [6] ./c.js 72 bytes {4} {5} [built] chunk {6} default/async-a.js (async-a) 176 bytes <{0}> ={7}= >{8}< [rendered] > ./a [0] ./index.js 1:0-47 - [1] ./d.js 20 bytes {1} {2} {3} {4} {5} {6} [built] - [10] ./a.js + 1 modules 156 bytes {1} {6} [built] - | ./a.js 121 bytes [built] - | ./e.js 20 bytes [built] - chunk {7} default/vendors.js (vendors) 112 bytes <{0}> ={2}= ={3}= ={4}= ={5}= ={6}= >{8}< [initial] [rendered] split chunk (cache group: vendors) (name: vendors) + [1] ./d.js 20 bytes {1} {2} {3} {4} {5} {6} [built] + [9] ./a.js + 1 modules 156 bytes {1} {6} [built] + | ./a.js 121 bytes [built] + | ./e.js 20 bytes [built] + chunk {7} default/vendors.js (vendors) 60 bytes <{0}> ={2}= ={3}= ={4}= ={5}= ={6}= >{8}< [initial] [rendered] split chunk (cache group: vendors) (name: vendors) > ./b b > ./c c > ./a [0] ./index.js 1:0-47 @@ -2697,12 +2696,11 @@ Child custom-chunks-filter-in-cache-groups: [2] ./node_modules/x.js 20 bytes {1} {7} [built] [3] ./node_modules/y.js 20 bytes {1} {7} [built] [7] ./node_modules/z.js 20 bytes {7} [built] - [8] multi x y z 52 bytes {7} [built] chunk {8} default/async-g.js (async-g) 54 bytes <{1}> <{6}> <{7}> [rendered] > ./g [] 6:0-47 > ./g [] 6:0-47 [5] ./f.js 20 bytes {2} {3} {4} {5} {8} [built] - [9] ./g.js 34 bytes {8} [built]" + [8] ./g.js 34 bytes {8} [built]" `; exports[`StatsTestCases should print correct stats for split-chunks-automatic-name 1`] = ` @@ -3015,7 +3013,7 @@ chunk {4} default/async-c.js (async-c) 48 bytes <{0}> ={2}= [rendered] `; exports[`StatsTestCases should print correct stats for tree-shaking 1`] = ` -"Hash: 40df5eaa38b35883e99e +"Hash: a66ca410afc2eb29b31d Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -3052,7 +3050,7 @@ Entrypoint main = bundle.js `; exports[`StatsTestCases should print correct stats for warnings-uglifyjs 1`] = ` -"Hash: ed8a6765253160add1c8 +"Hash: 3663bd94f10ad20afb9e Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names diff --git a/test/configCases/commons-chunk-plugin/hot-multi/first.js b/test/configCases/commons-chunk-plugin/hot-multi/first.js index 751a8042f..a5b1477a8 100644 --- a/test/configCases/commons-chunk-plugin/hot-multi/first.js +++ b/test/configCases/commons-chunk-plugin/hot-multi/first.js @@ -1,6 +1,5 @@ require("./common"); it("should have the correct main flag for multi first module", function() { - var multiModule = __webpack_require__.c[module.parents[0]]; - expect(multiModule.hot._main).toBe(true); + expect(module.hot._main).toBe(true); }); diff --git a/test/configCases/commons-chunk-plugin/hot-multi/second.js b/test/configCases/commons-chunk-plugin/hot-multi/second.js index fd42f8148..75f1494c3 100644 --- a/test/configCases/commons-chunk-plugin/hot-multi/second.js +++ b/test/configCases/commons-chunk-plugin/hot-multi/second.js @@ -1,6 +1,5 @@ require("./common"); it("should have the correct main flag for multi second module", function() { - var multiModule = __webpack_require__.c[module.parents[0]]; - expect(multiModule.hot._main).toBe(true); + expect(module.hot._main).toBe(true); }); diff --git a/test/configCases/commons-chunk-plugin/hot-multi/vendor.js b/test/configCases/commons-chunk-plugin/hot-multi/vendor.js index abba7de3a..99a0da0b7 100644 --- a/test/configCases/commons-chunk-plugin/hot-multi/vendor.js +++ b/test/configCases/commons-chunk-plugin/hot-multi/vendor.js @@ -3,6 +3,5 @@ require("./common"); module.exports = "vendor"; it("should have the correct main flag for multi vendor module", function() { - var multiModule = __webpack_require__.c[module.parents[0]]; - expect(multiModule.hot._main).toBe(true); + expect(module.hot._main).toBe(true); }); diff --git a/test/configCases/entry/adding-mulitple-entry-points/fail.js b/test/configCases/entry/adding-mulitple-entry-points/fail.js new file mode 100644 index 000000000..e5f60bc2f --- /dev/null +++ b/test/configCases/entry/adding-mulitple-entry-points/fail.js @@ -0,0 +1 @@ +// no test here, this will fail when only this entry is loaded diff --git a/test/configCases/entry/override-entry-point/ok.js b/test/configCases/entry/adding-mulitple-entry-points/ok.js similarity index 100% rename from test/configCases/entry/override-entry-point/ok.js rename to test/configCases/entry/adding-mulitple-entry-points/ok.js diff --git a/test/configCases/entry/override-entry-point/test.config.js b/test/configCases/entry/adding-mulitple-entry-points/test.config.js similarity index 100% rename from test/configCases/entry/override-entry-point/test.config.js rename to test/configCases/entry/adding-mulitple-entry-points/test.config.js diff --git a/test/configCases/entry/adding-mulitple-entry-points/webpack.config.js b/test/configCases/entry/adding-mulitple-entry-points/webpack.config.js new file mode 100644 index 000000000..b59321efe --- /dev/null +++ b/test/configCases/entry/adding-mulitple-entry-points/webpack.config.js @@ -0,0 +1,17 @@ +const EntryPlugin = require("../../../../lib/EntryPlugin"); +module.exports = { + entry: () => ({}), + optimization: { + runtimeChunk: true + }, + output: { + filename: "[name].js", + chunkFilename: "[name].chunk.js" + }, + target: "web", + plugins: [ + new EntryPlugin(__dirname, "./fail", "main"), + new EntryPlugin(__dirname, "./ok", "main"), + new EntryPlugin(__dirname, "./fail", "main") + ] +}; diff --git a/test/configCases/entry/override-entry-point/fail.js b/test/configCases/entry/override-entry-point/fail.js deleted file mode 100644 index bfab02f2f..000000000 --- a/test/configCases/entry/override-entry-point/fail.js +++ /dev/null @@ -1,3 +0,0 @@ -it("should load correct entry", function() { - throw new Error("This entrypoint should not be used"); -}); diff --git a/test/configCases/entry/override-entry-point/webpack.config.js b/test/configCases/entry/override-entry-point/webpack.config.js deleted file mode 100644 index 2eb94ff79..000000000 --- a/test/configCases/entry/override-entry-point/webpack.config.js +++ /dev/null @@ -1,16 +0,0 @@ -const SingleEntryPlugin = require("../../../../lib/SingleEntryPlugin"); -module.exports = { - entry: () => ({}), - optimization: { - runtimeChunk: true - }, - output: { - filename: "[name].js", - chunkFilename: "[name].chunk.js" - }, - target: "web", - plugins: [ - new SingleEntryPlugin(__dirname, "./fail", "main"), - new SingleEntryPlugin(__dirname, "./ok", "main") - ] -}; diff --git a/test/configCases/errors/multi-entry-missing-module/index.js b/test/configCases/errors/multi-entry-missing-module/index.js index e4dec7f22..b879d9379 100644 --- a/test/configCases/errors/multi-entry-missing-module/index.js +++ b/test/configCases/errors/multi-entry-missing-module/index.js @@ -1,9 +1,8 @@ -it("Should use WebpackMissingModule when module is missing with multiple entry setup", function() { - var fs = require("fs"); - var path = require("path"); - var source = fs.readFileSync(path.join(__dirname, "b.js"), "utf-8"); - expect(source).toMatch("!(function webpackMissingModule() { var e = new Error(\"Cannot find module './intentionally-missing-module.js'\"); e.code = 'MODULE_NOT_FOUND'; throw e; }());"); +it("should ignore missing modules as entries", function() { + // a.js and b.js should be evaulated correctly +}); +it("should use WebpackMissingModule when evaluating missing modules", function() { expect(function() { require("./intentionally-missing-module"); }).toThrowError("Cannot find module './intentionally-missing-module'"); diff --git a/test/configCases/errors/multi-entry-missing-module/test.config.js b/test/configCases/errors/multi-entry-missing-module/test.config.js new file mode 100644 index 000000000..50494000b --- /dev/null +++ b/test/configCases/errors/multi-entry-missing-module/test.config.js @@ -0,0 +1,9 @@ +module.exports = { + findBundle: function() { + return [ + "./a.js", + "./b.js", + "./bundle0.js" + ] + } +}; diff --git a/test/configCases/errors/multi-entry-missing-module/webpack.config.js b/test/configCases/errors/multi-entry-missing-module/webpack.config.js index 221fe4b45..9abc19e5c 100644 --- a/test/configCases/errors/multi-entry-missing-module/webpack.config.js +++ b/test/configCases/errors/multi-entry-missing-module/webpack.config.js @@ -1,14 +1,12 @@ const IgnorePlugin = require("../../../../lib/IgnorePlugin"); module.exports = { entry: { + a: "./intentionally-missing-module.js", b: ["./intentionally-missing-module.js"], bundle0: ["./index"] }, output: { filename: "[name].js" }, - plugins: [new IgnorePlugin(new RegExp(/intentionally-missing-module/))], - node: { - __dirname: false - } + plugins: [new IgnorePlugin(new RegExp(/intentionally-missing-module/))] }; diff --git a/test/statsCases/no-emit-on-errors-plugin-with-child-error/TestChildCompilationFailurePlugin.js b/test/statsCases/no-emit-on-errors-plugin-with-child-error/TestChildCompilationFailurePlugin.js index b0b504377..2ef90eacd 100644 --- a/test/statsCases/no-emit-on-errors-plugin-with-child-error/TestChildCompilationFailurePlugin.js +++ b/test/statsCases/no-emit-on-errors-plugin-with-child-error/TestChildCompilationFailurePlugin.js @@ -1,6 +1,6 @@ "use strict"; -var SingleEntryPlugin = require("../../../lib/SingleEntryPlugin"); +var EntryPlugin = require("../../../lib/EntryPlugin"); /** * Runs a child compilation which produces an error in order to test that NoEmitErrorsPlugin @@ -18,7 +18,7 @@ module.exports = class TestChildCompilationFailurePlugin { child.hooks.compilation.tap("TestChildCompilationFailurePlugin", childCompilation => { childCompilation.errors.push(new Error("forced error")); }); - new SingleEntryPlugin(compiler.options.context, compiler.options.entry, "child").apply(child); + new EntryPlugin(compiler.options.context, compiler.options.entry, "child").apply(child); child.runAsChild(cb); }); }