Merge pull request #7933 from webpack/refactor/module-graph

Refactor/module graph
This commit is contained in:
Tobias Koppers 2018-08-22 19:22:59 +02:00 committed by GitHub
commit 190a8af6d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 362 additions and 297 deletions

View File

@ -43,7 +43,7 @@ class AutomaticPrefetchPlugin {
asyncLib.forEach(
lastModules,
(m, callback) => {
compilation.prefetch(
compilation.addModuleChain(
m.context || compiler.context,
new PrefetchDependency(m.request),
callback

View File

@ -155,7 +155,7 @@ class Chunk {
this,
"Chunk.compareTo"
);
return chunkGraph.compareChunks(chunkGraph._moduleGraph, this, otherChunk);
return chunkGraph.compareChunks(this, otherChunk);
}
containsModule(module) {
@ -236,11 +236,7 @@ class Chunk {
this,
"Chunk.getChunkModuleMaps"
);
return chunkGraph.getChunkModuleMaps(
chunkGraph._moduleGraph,
this,
filterFn
);
return chunkGraph.getChunkModuleMaps(this, filterFn);
}
hasModuleInGraph(filterFn, filterChunkFn) {
@ -446,11 +442,10 @@ class Chunk {
}
/**
* @param {ModuleGraph} moduleGraph the module graph
* @param {ChunkGraph} chunkGraph the chunk graph
* @returns {Record<string, Set<TODO>[]>} a record object of names to lists of child ids(?)
*/
getChildIdsByOrders(moduleGraph, chunkGraph) {
getChildIdsByOrders(chunkGraph) {
const lists = new Map();
for (const group of this.groupsIterable) {
if (group.chunks[group.chunks.length - 1] === this) {
@ -474,7 +469,7 @@ class Chunk {
list.sort((a, b) => {
const cmp = b.order - a.order;
if (cmp !== 0) return cmp;
return a.group.compareTo(moduleGraph, chunkGraph, b.group);
return a.group.compareTo(chunkGraph, b.group);
});
result[name] = Array.from(
list.reduce((set, item) => {
@ -489,16 +484,15 @@ class Chunk {
}
/**
* @param {ModuleGraph} moduleGraph the module graph
* @param {ChunkGraph} chunkGraph the chunk graph
* @param {boolean=} includeDirectChildren include direct children (by default only children of async children are included)
* @returns {Record<string|number, Record<string, Set<TODO>[]>>} a record object of names to lists of child ids(?) by chunk id
*/
getChildIdsByOrdersMap(moduleGraph, chunkGraph, includeDirectChildren) {
getChildIdsByOrdersMap(chunkGraph, includeDirectChildren) {
const chunkMaps = Object.create(null);
const addChildIdsByOrdersToMap = chunk => {
const data = chunk.getChildIdsByOrders(moduleGraph, chunkGraph);
const data = chunk.getChildIdsByOrders(chunkGraph);
for (const key of Object.keys(data)) {
let chunkMap = chunkMaps[key];
if (chunkMap === undefined) {

View File

@ -361,12 +361,11 @@ class ChunkGraph {
*/
/**
* @param {ModuleGraph} moduleGraph the module graph
* @param {Chunk} chunk the chunk
* @param {ModuleFilterPredicate} filterFn function used to filter modules
* @returns {ChunkModuleMaps} module map information
*/
getChunkModuleMaps(moduleGraph, chunk, filterFn) {
getChunkModuleMaps(chunk, filterFn) {
/** @type {Record<string|number, (string|number)[]>} */
const chunkModuleIdMap = Object.create(null);
/** @type {Record<string|number, string>} */
@ -377,7 +376,7 @@ class ChunkGraph {
let array;
for (const module of this.getOrderedChunkModulesIterable(
asyncChunk,
compareModulesById(moduleGraph)
compareModulesById(this._moduleGraph)
)) {
if (filterFn(module)) {
if (array === undefined) {
@ -430,17 +429,16 @@ class ChunkGraph {
}
/**
* @param {ModuleGraph} moduleGraph the module graph
* @param {Chunk} chunkA first chunk
* @param {Chunk} chunkB second chunk
* @returns {-1|0|1} this is a comparitor function like sort and returns -1, 0, or 1 based on sort order
*/
compareChunks(moduleGraph, chunkA, chunkB) {
compareChunks(chunkA, chunkB) {
const cgcA = this._getChunkGraphChunk(chunkA);
const cgcB = this._getChunkGraphChunk(chunkB);
if (cgcA.modules.size > cgcB.modules.size) return -1;
if (cgcA.modules.size < cgcB.modules.size) return 1;
const cmpFn = compareModulesById(moduleGraph);
const cmpFn = compareModulesById(this._moduleGraph);
cgcA.modules.sortWith(cmpFn);
cgcB.modules.sortWith(cmpFn);
const a = cgcA.modules[Symbol.iterator]();

View File

@ -402,12 +402,11 @@ class ChunkGroup {
* Sorting predicate which allows current ChunkGroup to be compared against another.
* Sorting values are based off of number of chunks in ChunkGroup.
*
* @param {ModuleGraph} moduleGraph the module graph
* @param {ChunkGraph} chunkGraph the chunk graph
* @param {ChunkGroup} otherGroup the chunkGroup to compare this against
* @returns {-1|0|1} sort position for comparison
*/
compareTo(moduleGraph, chunkGraph, otherGroup) {
compareTo(chunkGraph, otherGroup) {
if (this.chunks.length > otherGroup.chunks.length) return -1;
if (this.chunks.length < otherGroup.chunks.length) return 1;
const a = this.chunks[Symbol.iterator]();
@ -417,11 +416,7 @@ class ChunkGroup {
const aItem = a.next();
const bItem = b.next();
if (aItem.done) return 0;
const cmp = chunkGraph.compareChunks(
moduleGraph,
aItem.value,
bItem.value
);
const cmp = chunkGraph.compareChunks(aItem.value, bItem.value);
if (cmp !== 0) return cmp;
}
}
@ -455,7 +450,7 @@ class ChunkGroup {
list.sort((a, b) => {
const cmp = b.order - a.order;
if (cmp !== 0) return cmp;
return a.group.compareTo(moduleGraph, chunkGraph, b.group);
return a.group.compareTo(chunkGraph, b.group);
});
result[name] = list.map(i => i.group);
}

View File

@ -33,6 +33,7 @@ const ModuleDependencyError = require("./ModuleDependencyError");
const ModuleDependencyWarning = require("./ModuleDependencyWarning");
const ModuleGraph = require("./ModuleGraph");
const ModuleNotFoundError = require("./ModuleNotFoundError");
const ModuleProfile = require("./ModuleProfile");
const ModuleTemplate = require("./ModuleTemplate");
const RuntimeTemplate = require("./RuntimeTemplate");
const Stats = require("./Stats");
@ -337,9 +338,11 @@ class Compilation {
const options = (this.options = compiler.options);
this.outputOptions = options && options.output;
/** @type {boolean=} */
this.bail = options && options.bail;
this.profile = options && options.profile;
/** @type {boolean} */
this.bail = (options && options.bail) || false;
/** @type {boolean} */
this.profile = (options && options.profile) || false;
// TODO webpack 5 remove this property
this.performance = options && options.performance;
this.mainTemplate = new MainTemplate(this.outputOptions);
@ -407,6 +410,8 @@ class Compilation {
this.compilationDependencies = undefined;
/** @type {boolean} */
this.needAdditionalPass = false;
/** @type {WeakSet<Module>} */
this.builtModules = new WeakSet();
/** @private @type {Map<Module, Callback[]>} */
this._buildingModules = new Map();
/** @private @type {Map<Module, Callback[]>} */
@ -466,6 +471,7 @@ class Compilation {
for (const err of cacheModule.warnings) {
this.warnings.push(err);
}
ModuleGraph.setModuleGraphForModule(cacheModule, this.moduleGraph);
return {
module: cacheModule,
issuer: true,
@ -481,6 +487,7 @@ class Compilation {
this.cache[cacheName] = module;
}
this.modules.push(module);
ModuleGraph.setModuleGraphForModule(module, this.moduleGraph);
return {
module: module,
issuer: true,
@ -548,6 +555,7 @@ class Compilation {
};
this.hooks.buildModule.call(module);
this.builtModules.add(module);
module.build(
this.options,
this,
@ -674,8 +682,9 @@ class Compilation {
recursive,
callback
) {
const start = this.profile && Date.now();
const currentProfile = this.profile && {};
let currentProfile = this.profile ? new ModuleProfile() : undefined;
const moduleGraph = this.moduleGraph;
asyncLib.forEach(
dependencies,
@ -712,8 +721,6 @@ class Compilation {
dependencies: dependencies
},
(err, dependentModule) => {
let afterFactory;
const isOptional = () => {
return dependencies.every(d => d.optional);
};
@ -736,19 +743,14 @@ class Compilation {
semaphore.release();
return process.nextTick(callback);
}
if (currentProfile) {
afterFactory = Date.now();
currentProfile.factory = afterFactory - start;
if (currentProfile !== undefined) {
currentProfile.markFactoryEnd();
}
const iterationDependencies = depend => {
for (let index = 0; index < depend.length; index++) {
const dep = depend[index];
this.moduleGraph.setResolvedModule(
module,
dep,
dependentModule
);
moduleGraph.setResolvedModule(module, dep, dependentModule);
}
};
@ -760,9 +762,8 @@ class Compilation {
iterationDependencies(dependencies);
const afterBuild = () => {
if (currentProfile) {
const afterBuilding = Date.now();
currentProfile.building = afterBuilding - afterFactory;
if (currentProfile !== undefined) {
currentProfile.markBuildingEnd();
}
if (recursive && addModuleResult.dependencies) {
@ -773,21 +774,17 @@ class Compilation {
};
if (addModuleResult.issuer) {
if (currentProfile) {
dependentModule.profile = currentProfile;
if (currentProfile !== undefined) {
moduleGraph.setProfile(dependentModule, currentProfile);
}
this.moduleGraph.setIssuer(dependentModule, module);
moduleGraph.setIssuer(dependentModule, module);
} else {
if (this.profile) {
if (module.profile) {
const time = Date.now() - start;
if (
!module.profile.dependencies ||
time > module.profile.dependencies
) {
module.profile.dependencies = time;
}
if (currentProfile !== undefined) {
currentProfile.markAdditionalFactoryEnd(
moduleGraph.getProfile(module)
);
}
}
}
@ -804,9 +801,8 @@ class Compilation {
return errorOrWarningAndCallback(err);
}
if (currentProfile) {
const afterBuilding = Date.now();
currentProfile.building = afterBuilding - afterFactory;
if (currentProfile !== undefined) {
currentProfile.markBuildingEnd();
}
semaphore.release();
@ -841,13 +837,12 @@ class Compilation {
*
* @param {string} context context string path
* @param {Dependency} dependency dependency used to create Module chain
* @param {OnModuleCallback} onModule function invoked on modules creation
* @param {ModuleChainCallback} callback callback for when module chain is complete
* @returns {void} will throw if dependency instance is not a valid Dependency
*/
_addModuleChain(context, dependency, onModule, callback) {
const start = this.profile && Date.now();
const currentProfile = this.profile && {};
addModuleChain(context, dependency, callback) {
let currentProfile = this.profile ? new ModuleProfile() : undefined;
const moduleGraph = this.moduleGraph;
const errorAndCallback = this.bail
? err => {
@ -892,11 +887,8 @@ class Compilation {
return errorAndCallback(new EntryModuleNotFoundError(err));
}
let afterFactory;
if (currentProfile) {
afterFactory = Date.now();
currentProfile.factory = afterFactory - start;
if (currentProfile !== undefined) {
currentProfile.markFactoryEnd();
}
if (!module) {
@ -907,14 +899,11 @@ class Compilation {
const addModuleResult = this.addModule(module);
module = addModuleResult.module;
onModule(module);
this.moduleGraph.setResolvedModule(null, dependency, module);
moduleGraph.setResolvedModule(null, dependency, module);
const afterBuild = () => {
if (currentProfile) {
const afterBuilding = Date.now();
currentProfile.building = afterBuilding - afterFactory;
if (currentProfile !== undefined) {
currentProfile.markBuildingEnd();
}
if (addModuleResult.dependencies) {
@ -927,9 +916,11 @@ class Compilation {
}
};
if (currentProfile !== undefined) {
if (addModuleResult.issuer) {
if (currentProfile) {
module.profile = currentProfile;
moduleGraph.setProfile(module, currentProfile);
} else {
currentProfile = undefined;
}
}
@ -940,9 +931,8 @@ class Compilation {
return errorAndCallback(err);
}
if (currentProfile) {
const afterBuilding = Date.now();
currentProfile.building = afterBuilding - afterFactory;
if (currentProfile !== undefined) {
currentProfile.markBuildingEnd();
}
this.semaphore.release();
@ -973,24 +963,7 @@ class Compilation {
}
entriesArray.push(entry);
this._addModuleChain(context, entry, module => {}, callback);
}
/**
* @param {string} context context path string
* @param {Dependency} dependency dep used to create module
* @param {ModuleCallback} callback module callback sending module up a level
* @returns {void}
*/
prefetch(context, dependency, callback) {
this._addModuleChain(
context,
dependency,
module => {
module.prefetched = true;
},
callback
);
this.addModuleChain(context, entry, callback);
}
/**
@ -1311,20 +1284,20 @@ class Compilation {
* @returns {void}
*/
assignDepth(module) {
const moduleGraph = this.moduleGraph;
const queue = new Set([module]);
let depth;
module.depth = 0;
moduleGraph.setDepth(module, 0);
/**
* @param {Module} module module for processeing
* @returns {void}
*/
const enqueueJob = module => {
const d = module.depth;
if (typeof d === "number" && d <= depth) return;
if (!moduleGraph.setDepthIfLower(module, depth)) return;
queue.add(module);
module.depth = depth;
};
/**
@ -1354,9 +1327,8 @@ class Compilation {
for (module of queue) {
queue.delete(module);
depth = module.depth;
depth = moduleGraph.getDepth(module) + 1;
depth++;
assignDepthToDependencyBlock(module);
}
}

View File

@ -236,7 +236,6 @@ class ContextModule extends Module {
* @returns {void}
*/
build(options, compilation, resolver, fs, callback) {
this.built = true;
this.buildMeta = {};
this.buildInfo = {
builtTime: Date.now(),

View File

@ -82,7 +82,6 @@ class DelegatedModule extends Module {
* @returns {void}
*/
build(options, compilation, resolver, fs, callback) {
this.built = true;
this.buildMeta = Object.assign({}, this.delegateData.buildMeta);
this.buildInfo = {};
this.delegatedSourceDependency = new DelegatedSourceDependency(

View File

@ -50,7 +50,6 @@ class DllModule extends Module {
* @returns {void}
*/
build(options, compilation, resolver, fs, callback) {
this.built = true;
this.buildMeta = {};
this.buildInfo = {};
return callback();

View File

@ -163,7 +163,6 @@ class ExternalModule extends Module {
* @returns {void}
*/
build(options, compilation, resolver, fs, callback) {
this.built = true;
this.buildMeta = {};
this.buildInfo = {};
callback();

View File

@ -316,7 +316,7 @@ module.exports = class HotModuleReplacementPlugin {
chunk: hotUpdateChunk,
dependencyTemplates: compilation.dependencyTemplates,
runtimeTemplate: compilation.runtimeTemplate,
moduleGraph: compilation.moduleGraph,
moduleGraph,
chunkGraph: compilation.chunkGraph
},
compilation.moduleTemplates.javascript,

View File

@ -159,7 +159,7 @@ class JavascriptModulesPlugin {
chunk,
dependencyTemplates,
runtimeTemplate: compilation.runtimeTemplate,
moduleGraph: compilation.moduleGraph,
moduleGraph,
chunkGraph: compilation.chunkGraph
}
),

View File

@ -49,7 +49,7 @@ class LibManifestPlugin {
module => {
if (
this.options.entryOnly &&
!compilation.moduleGraph
!moduleGraph
.getIncomingConnections(module)
.some(c => c.dependency instanceof EntryDependency)
) {

View File

@ -103,14 +103,6 @@ class Module extends DependenciesBlock {
// Info from Compilation (per Compilation)
/** @type {number|string} */
this.id = null;
/** @type {number} */
this.depth = null;
/** @type {undefined | object} */
this.profile = undefined;
/** @type {boolean} */
this.prefetched = false;
/** @type {boolean} */
this.built = false;
/** @type {boolean} */
this.useSourceMap = false;
@ -118,6 +110,20 @@ class Module extends DependenciesBlock {
// TODO remove in webpack 6
// BACKWARD-COMPAT START
get profile() {
return ModuleGraph.getModuleGraphForModule(
this,
"Module.profile"
).getProfile(this);
}
set profile(value) {
ModuleGraph.getModuleGraphForModule(this, "Module.profile").setProfile(
this,
value
);
}
get index() {
return ModuleGraph.getModuleGraphForModule(
this,
@ -146,6 +152,19 @@ class Module extends DependenciesBlock {
).setPostOrderIndex(this, value);
}
get depth() {
return ModuleGraph.getModuleGraphForModule(this, "Module.depth").getDepth(
this
);
}
set depth(value) {
ModuleGraph.getModuleGraphForModule(this, "Module.depth").setDepth(
this,
value
);
}
get issuer() {
return ModuleGraph.getModuleGraphForModule(this, "Module.issuer").getIssuer(
this
@ -261,10 +280,6 @@ class Module extends DependenciesBlock {
this.renderedHash = undefined;
this.id = null;
this.depth = null;
this.profile = undefined;
this.prefetched = false;
this.built = false;
super.disconnect();
}
@ -274,7 +289,6 @@ class Module extends DependenciesBlock {
*/
unseal() {
this.id = null;
this.depth = null;
super.unseal();
}

View File

@ -11,6 +11,7 @@ const ModuleGraphConnection = require("./ModuleGraphConnection");
/** @typedef {import("./DependenciesBlock")} DependenciesBlock */
/** @typedef {import("./Dependency")} Dependency */
/** @typedef {import("./Module")} Module */
/** @typedef {import("./ModuleProfile")} ModuleProfile */
/** @typedef {import("./RequestShortener")} RequestShortener */
/** @template T @typedef {import("./util/SortableSet")<T>} SortableSet<T> */
@ -32,6 +33,10 @@ class ModuleGraphModule {
this.preOrderIndex = null;
/** @type {number} */
this.postOrderIndex = null;
/** @type {number} */
this.depth = null;
/** @type {ModuleProfile} */
this.profile = undefined;
}
}
@ -170,8 +175,10 @@ class ModuleGraph {
const newMgm = this._getModuleGraphModule(newModule);
newMgm.postOrderIndex = oldMgm.postOrderIndex;
newMgm.preOrderIndex = oldMgm.preOrderIndex;
newMgm.depth = oldMgm.depth;
oldMgm.postOrderIndex = null;
oldMgm.preOrderIndex = null;
oldMgm.depth = null;
}
/**
@ -182,6 +189,7 @@ class ModuleGraph {
const mgm = this._getModuleGraphModule(module);
mgm.postOrderIndex = null;
mgm.preOrderIndex = null;
mgm.depth = null;
}
/**
@ -191,6 +199,7 @@ class ModuleGraph {
for (const mgm of this._moduleMap.values()) {
mgm.postOrderIndex = null;
mgm.preOrderIndex = null;
mgm.depth = null;
}
}
@ -299,6 +308,25 @@ class ModuleGraph {
return Array.from(connections);
}
/**
* @param {Module} module the module
* @returns {ModuleProfile | null} the module profile
*/
getProfile(module) {
const mgm = this._getModuleGraphModule(module);
return mgm.profile;
}
/**
* @param {Module} module the module
* @param {ModuleProfile | null} profile the module profile
* @returns {void}
*/
setProfile(module, profile) {
const mgm = this._getModuleGraphModule(module);
mgm.profile = profile;
}
/**
* @param {Module} module the module
* @returns {Module | null} the issuer module
@ -417,6 +445,39 @@ class ModuleGraph {
return false;
}
/**
* @param {Module} module the module
* @returns {number} the depth of the module
*/
getDepth(module) {
const mgm = this._getModuleGraphModule(module);
return mgm.depth;
}
/**
* @param {Module} module the module
* @param {number} depth the depth of the module
* @returns {void}
*/
setDepth(module, depth) {
const mgm = this._getModuleGraphModule(module);
mgm.depth = depth;
}
/**
* @param {Module} module the module
* @param {number} depth the depth of the module
* @returns {boolean} true, if the depth was set
*/
setDepthIfLower(module, depth) {
const mgm = this._getModuleGraphModule(module);
if (mgm.depth === null || mgm.depth > depth) {
mgm.depth = depth;
return true;
}
return false;
}
/**
* @param {any} thing any thing
* @returns {Object} metadata

34
lib/ModuleProfile.js Normal file
View File

@ -0,0 +1,34 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
class ModuleProfile {
constructor() {
this.startTime = Date.now();
this.factory = 0;
this.building = 0;
this.additionalFactories = 0;
}
markFactoryEnd() {
this.factoryTime = Date.now();
this.factory = this.factoryTime - this.startTime;
}
markBuildingEnd() {
this.buildingTime = Date.now();
this.building = this.buildingTime - this.factoryTime;
}
markAdditionalFactoryEnd(realProfile) {
const additionalFactories = Date.now() - this.startTime;
if (additionalFactories > realProfile.additionalFactories)
realProfile.additionalFactories = additionalFactories;
return realProfile;
}
}
module.exports = ModuleProfile;

View File

@ -421,7 +421,6 @@ class NormalModule extends Module {
*/
build(options, compilation, resolver, fs, callback) {
this.buildTimestamp = Date.now();
this.built = true;
this._source = null;
this._ast = null;
this._buildHash = "";

View File

@ -28,7 +28,7 @@ class PrefetchPlugin {
}
);
compiler.hooks.make.tapAsync("PrefetchPlugin", (compilation, callback) => {
compilation.prefetch(
compilation.addModuleChain(
this.context || compiler.context,
new PrefetchDependency(this.request),
callback

View File

@ -22,7 +22,6 @@ module.exports = class RawModule extends Module {
this.sourceStr = source;
this.identifierStr = identifier || this.sourceStr;
this.readableIdentifierStr = readableIdentifier || this.identifierStr;
this.built = false;
}
/**
@ -65,7 +64,6 @@ module.exports = class RawModule extends Module {
* @returns {void}
*/
build(options, compilation, resolver, fs, callback) {
this.built = true;
this.buildMeta = {};
this.buildInfo = {
cacheable: true

View File

@ -17,6 +17,7 @@ const identifierUtils = require("./util/identifier");
/** @typedef {import("./Chunk")} Chunk */
/** @typedef {import("./ChunkGroup")} ChunkGroup */
/** @typedef {import("./Compilation")} Compilation */
/** @typedef {import("./ModuleProfile")} ModuleProfile */
const optionsOrFallback = (...args) => {
let optionValues = [];
@ -24,6 +25,22 @@ const optionsOrFallback = (...args) => {
return optionValues.find(optionValue => optionValue !== undefined);
};
// remove a prefixed "!" that can be specified to reverse sort order
const normalizeFieldKey = field => {
if (field[0] === "!") {
return field.substr(1);
}
return field;
};
// if a field is prefixed by a "!" reverse sort order
const sortOrderRegular = field => {
if (field[0] === "!") {
return false;
}
return true;
};
class Stats {
/**
* @param {Compilation} compilation webpack compilation
@ -86,22 +103,6 @@ class Stats {
);
}
// remove a prefixed "!" that can be specified to reverse sort order
normalizeFieldKey(field) {
if (field[0] === "!") {
return field.substr(1);
}
return field;
}
// if a field is prefixed by a "!" reverse sort order
sortOrderRegular(field) {
if (field[0] === "!") {
return false;
}
return true;
}
toJson(options, forToString) {
if (typeof options === "boolean" || typeof options === "string") {
options = Stats.presetToOptions(options);
@ -233,7 +234,9 @@ class Stats {
}
if (!showCachedModules) {
excludeModules.push((ident, module) => !module.built);
excludeModules.push(
(ident, module) => !compilation.builtModules.has(module)
);
}
const createModuleFilter = type => {
@ -261,29 +264,39 @@ class Stats {
};
};
const sortByFieldAndOrder = (fieldKey, a, b) => {
if (a[fieldKey] === null && b[fieldKey] === null) return 0;
if (a[fieldKey] === null) return 1;
if (b[fieldKey] === null) return -1;
if (a[fieldKey] === b[fieldKey]) return 0;
return a[fieldKey] < b[fieldKey] ? -1 : 1;
const sortByGetter = (getter, fallback) => (a, b) => {
const aValue = getter(a);
const bValue = getter(b);
if (aValue === null && bValue === null) return 0;
if (aValue === null) return 1;
if (bValue === null) return -1;
if (aValue === bValue) return fallback ? fallback(a, b) : 0;
return aValue < bValue ? -1 : 1;
};
const sortByField = field => (a, b) => {
const sortRealModules = sortByGetter(
m => moduleGraph.getDepth(m),
sortByGetter(m => moduleGraph.getPreOrderIndex(m))
);
const sortByField = field => {
if (!field) {
return 0;
return () => 0;
}
const fieldKey = this.normalizeFieldKey(field);
const fieldKey = normalizeFieldKey(field);
let sortFn = sortByGetter(m => m[fieldKey]);
// if a field is prefixed with a "!" the sort is reversed!
const sortIsRegular = this.sortOrderRegular(field);
const sortIsRegular = sortOrderRegular(field);
return sortByFieldAndOrder(
fieldKey,
sortIsRegular ? a : b,
sortIsRegular ? b : a
);
if (!sortIsRegular) {
const oldSortFn = sortFn;
sortFn = (a, b) => oldSortFn(b, a);
}
return sortFn;
};
const formatError = e => {
@ -505,6 +518,23 @@ class Stats {
obj.namedChunkGroups = fnChunkGroup(compilation.namedChunkGroups);
}
/**
* @param {ModuleProfile} profile the profile of the module
* @returns {any} stats info
*/
const fnProfile = profile => {
if (!profile) return undefined;
return {
factory: profile.factory,
building: profile.building,
additionalResolving: profile.additionalFactories,
// TODO remove this in webpack 6
resolving: profile.factory,
// TODO remove this in webpack 6
dependencies: profile.additionalFactories
};
};
const fnModule = (module, nested) => {
const path = [];
const issuer = moduleGraph.getIssuer(module);
@ -524,9 +554,8 @@ class Stats {
postOrderIndex: moduleGraph.getPostOrderIndex(module),
size: module.size(),
cacheable: module.buildInfo.cacheable,
built: !!module.built,
built: compilation.builtModules.has(module),
optional: module.isOptional(moduleGraph),
prefetched: module.prefetched,
chunks: Array.from(
chunkGraph.getOrderedModuleChunksIterable(module, compareChunksById),
chunk => chunk.id
@ -540,9 +569,9 @@ class Stats {
id: module.id,
identifier: module.identifier(),
name: module.readableIdentifier(requestShortener),
profile: module.profile
profile: fnProfile(moduleGraph.getProfile(module))
})),
profile: module.profile,
profile: fnProfile(moduleGraph.getProfile(module)),
failed: !!module.error,
errors: module.errors ? module.errors.length : 0,
warnings: module.warnings ? module.warnings.length : 0
@ -554,7 +583,7 @@ class Stats {
obj.assets = Object.keys(module.buildInfo.assets || {});
}
if (showReasons) {
obj.reasons = this.compilation.moduleGraph
obj.reasons = moduleGraph
.getIncomingConnections(module)
.sort((a, b) => {
if (a.originModule && !b.originModule) return -1;
@ -626,13 +655,12 @@ class Stats {
});
}
if (showDepth) {
obj.depth = module.depth;
obj.depth = moduleGraph.getDepth(module);
}
if (showNestedModules) {
if (module.modules) {
const modules = module.modules;
obj.modules = modules
.sort(sortByField("depth"))
.filter(createModuleFilter("nested"))
.map(m => fnModule(m, true));
obj.filteredModules = modules.length - obj.modules.length;
@ -649,10 +677,7 @@ class Stats {
const parents = new Set();
const children = new Set();
const siblings = new Set();
const childIdByOrder = chunk.getChildIdsByOrders(
moduleGraph,
chunkGraph
);
const childIdByOrder = chunk.getChildIdsByOrders(chunkGraph);
for (const chunkGroup of chunk.groupsIterable) {
for (const parentGroup of chunkGroup.parentsIterable) {
for (const chunk of parentGroup.chunks) {
@ -688,7 +713,7 @@ class Stats {
obj.modules = chunkGraph
.getChunkModules(chunk)
.slice()
.sort(sortByField("depth"))
.sort(sortRealModules)
.filter(createModuleFilter("chunk"))
.map(m => fnModule(m));
obj.filteredModules =
@ -738,7 +763,7 @@ class Stats {
if (showModules) {
obj.modules = compilation.modules
.slice()
.sort(sortByField("depth"))
.sort(sortRealModules)
.filter(createModuleFilter("module"))
.map(m => fnModule(m));
obj.filteredModules = compilation.modules.length - obj.modules.length;
@ -1078,10 +1103,9 @@ class Stats {
}]`
);
}
if (module.prefetched) {
colors.magenta(" [prefetched]");
if (module.failed) {
colors.red(" [failed]");
}
if (module.failed) colors.red(" [failed]");
if (module.warnings) {
colors.yellow(
` [${module.warnings} warning${module.warnings === 1 ? "" : "s"}]`
@ -1174,30 +1198,29 @@ class Stats {
}
if (module.profile) {
colors.normal(prefix);
let sum = 0;
if (module.issuerPath) {
for (const m of module.issuerPath) {
colors.normal("[");
colors.normal(m.id);
colors.normal("] ");
if (m.profile) {
const time = (m.profile.factory || 0) + (m.profile.building || 0);
const time = m.profile.resolving + m.profile.building;
coloredTime(time);
sum += time;
colors.normal(" ");
}
colors.normal("-> ");
}
}
for (const key of Object.keys(module.profile)) {
colors.normal(`${key}:`);
const time = module.profile[key];
coloredTime(time);
colors.normal(" ");
sum += time;
coloredTime(module.profile.resolving + module.profile.building);
colors.normal(" (resolving: ");
coloredTime(module.profile.resolving);
colors.normal(", building: ");
coloredTime(module.profile.building);
if (module.profile.additionalResolving) {
colors.normal(", additional resolving: ");
coloredTime(module.profile.additionalResolving);
}
colors.normal("= ");
coloredTime(sum);
colors.normal(")");
newline();
}
if (module.modules) {

View File

@ -320,9 +320,6 @@ class ConcatenatedModule extends Module {
this.rootModule = rootModule;
this.factoryMeta = rootModule.factoryMeta;
// Info from Compilation
this.depth = rootModule.depth;
// Info from Optimization
moduleGraph.setUsedExports(this, moduleGraph.getUsedExports(rootModule));
@ -338,7 +335,6 @@ class ConcatenatedModule extends Module {
contextDependencies: new Set(),
assets: undefined
};
this.built = modulesArray.some(m => m.built);
this.buildMeta = rootModule.buildMeta;
// Caching

View File

@ -272,7 +272,7 @@ class ModuleConcatenationPlugin {
// modules with lower depth are more likely suited as roots
// this improves performance, because modules already selected as inner are skipped
relevantModules.sort((a, b) => {
return a.depth - b.depth;
return moduleGraph.getDepth(a) - moduleGraph.getDepth(b);
});
const concatConfigurations = [];
const usedAsInner = new Set();
@ -343,6 +343,10 @@ class ModuleConcatenationPlugin {
moduleGraph.moveModuleAttributes(rootModule, newModule);
for (const m of modules) {
usedModules.add(m);
// add to builtModules when one of the included modules was built
if (compilation.builtModules.has(m)) {
compilation.builtModules.add(newModule);
}
// remove attributes from module
moduleGraph.removeModuleAttributes(m);
// remove module from chunk

View File

@ -193,17 +193,13 @@ class WasmMainTemplatePlugin {
"WasmMainTemplatePlugin",
(source, chunk) => {
const wasmModules = getAllWasmModules(
this.compilation.moduleGraph,
moduleGraph,
this.compilation.chunkGraph,
chunk
);
if (wasmModules.length === 0) return source;
const importObjects = wasmModules.map(module => {
return generateImportObject(
this.compilation.moduleGraph,
module,
this.mangleImports
);
return generateImportObject(moduleGraph, module, this.mangleImports);
});
return Template.asString([
source,
@ -230,7 +226,6 @@ class WasmMainTemplatePlugin {
mainTemplate.outputOptions.webassemblyModuleFilename;
const chunkModuleMaps = this.compilation.chunkGraph.getChunkModuleMaps(
moduleGraph,
chunk,
m => m.type.startsWith("webassembly")
);
@ -381,13 +376,12 @@ class WasmMainTemplatePlugin {
"WasmMainTemplatePlugin",
(hash, chunk) => {
const chunkModuleMaps = this.compilation.chunkGraph.getChunkModuleMaps(
moduleGraph,
chunk,
m => m.type.startsWith("webassembly")
);
hash.update(JSON.stringify(chunkModuleMaps.id));
const wasmModules = getAllWasmModules(
this.compilation.moduleGraph,
moduleGraph,
this.compilation.chunkGraph,
chunk
);

View File

@ -91,7 +91,7 @@ class WebAssemblyModulesPlugin {
chunk,
dependencyTemplates,
runtimeTemplate: compilation.runtimeTemplate,
moduleGraph: compilation.moduleGraph,
moduleGraph,
chunkGraph: compilation.chunkGraph
}
),
@ -125,7 +125,7 @@ class WebAssemblyModulesPlugin {
compilation.errors.push(
new WebAssemblyInInitialChunkError(
module,
compilation.moduleGraph,
moduleGraph,
compilation.chunkGraph,
compilation.requestShortener
)

View File

@ -25,17 +25,13 @@ class JsonpChunkTemplatePlugin {
* @returns {void}
*/
apply(chunkTemplate) {
const moduleGraph = this.compilation.moduleGraph;
chunkTemplate.hooks.render.tap(
"JsonpChunkTemplatePlugin",
(modules, moduleTemplate, { chunk, chunkGraph }) => {
const jsonpFunction = chunkTemplate.outputOptions.jsonpFunction;
const globalObject = chunkTemplate.outputOptions.globalObject;
const source = new ConcatSource();
const prefetchChunks = chunk.getChildIdsByOrders(
moduleGraph,
chunkGraph
).prefetch;
const prefetchChunks = chunk.getChildIdsByOrders(chunkGraph).prefetch;
source.add(
`(${globalObject}[${JSON.stringify(
jsonpFunction
@ -70,9 +66,7 @@ class JsonpChunkTemplatePlugin {
const chunkGraph = this.compilation.chunkGraph;
hash.update(JSON.stringify(getEntryInfo(chunkGraph, chunk)));
hash.update(
JSON.stringify(
chunk.getChildIdsByOrders(moduleGraph, chunkGraph).prefetch
) || ""
JSON.stringify(chunk.getChildIdsByOrders(chunkGraph).prefetch) || ""
);
}
);

View File

@ -46,7 +46,6 @@ class JsonpMainTemplatePlugin {
* @returns {void}
*/
apply(mainTemplate) {
const moduleGraph = this.compilation.moduleGraph;
const needChunkOnDemandLoadingCode = chunk => {
for (const chunkGroup of chunk.groupsIterable) {
if (chunkGroup.getNumberOfChildren() > 0) return true;
@ -68,7 +67,6 @@ class JsonpMainTemplatePlugin {
};
const needPrefetchingCode = chunk => {
const allPrefetchChunks = chunk.getChildIdsByOrdersMap(
moduleGraph,
this.compilation.chunkGraph,
true
).prefetch;
@ -333,7 +331,6 @@ class JsonpMainTemplatePlugin {
}),
(source, chunkIdExpression, { chunk, hash }) => {
const chunkMap = chunk.getChildIdsByOrdersMap(
moduleGraph,
this.compilation.chunkGraph
).preload;
if (!chunkMap || Object.keys(chunkMap).length === 0) return source;
@ -517,10 +514,7 @@ class JsonpMainTemplatePlugin {
"JsonpMainTemplatePlugin",
(source, chunk, hash) => {
const chunkGraph = this.compilation.chunkGraph;
const prefetchChunks = chunk.getChildIdsByOrders(
moduleGraph,
chunkGraph
).prefetch;
const prefetchChunks = chunk.getChildIdsByOrders(chunkGraph).prefetch;
if (
needChunkLoadingCode(chunk) &&
prefetchChunks &&

View File

@ -132,7 +132,7 @@ describe("StatsTestCases", () => {
.replace(/\r\n?/g, "\n")
.replace(/[\t ]*Version:.+\n/g, "")
.replace(path.join(base, testName), "Xdir/" + testName)
.replace(/ dependencies:Xms/g, "");
.replace(/, additional resolving: Xms/g, "");
expect(actual).toMatchSnapshot();
done();
});

View File

@ -171,32 +171,32 @@ exports[`StatsTestCases should print correct stats for async-commons-chunk-auto
[2] ./node_modules/x.js 20 bytes {1} {2} {3} {4} {5} {6} [built]
[3] ./node_modules/y.js 20 bytes {1} {2} {3} {4} [built]
[7] ./a.js + 1 modules 156 bytes {3} {4} [built]
| ./a.js 121 bytes [built]
| ./e.js 20 bytes [built]
| ./a.js 121 bytes [built]
chunk {4} disabled/async-a.js (async-a) 216 bytes <{0}> >{7}< [rendered]
> ./a [0] ./index.js 1:0-47
[1] ./d.js 20 bytes {1} {2} {3} {4} {5} {6} [built]
[2] ./node_modules/x.js 20 bytes {1} {2} {3} {4} {5} {6} [built]
[3] ./node_modules/y.js 20 bytes {1} {2} {3} {4} [built]
[7] ./a.js + 1 modules 156 bytes {3} {4} [built]
| ./a.js 121 bytes [built]
| ./e.js 20 bytes [built]
| ./a.js 121 bytes [built]
chunk {5} disabled/c.js (c) 167 bytes [entry] [rendered]
> ./c c
[1] ./d.js 20 bytes {1} {2} {3} {4} {5} {6} [built]
[2] ./node_modules/x.js 20 bytes {1} {2} {3} {4} {5} {6} [built]
[5] ./f.js 20 bytes {1} {2} {5} {6} {7} [built]
[8] ./c.js + 1 modules 107 bytes {5} {6} [built]
| ./c.js 72 bytes [built]
| ./node_modules/z.js 20 bytes [built]
| ./c.js 72 bytes [built]
chunk {6} disabled/async-c.js (async-c) 167 bytes <{0}> [rendered]
> ./c [0] ./index.js 3:0-47
[1] ./d.js 20 bytes {1} {2} {3} {4} {5} {6} [built]
[2] ./node_modules/x.js 20 bytes {1} {2} {3} {4} {5} {6} [built]
[5] ./f.js 20 bytes {1} {2} {5} {6} {7} [built]
[8] ./c.js + 1 modules 107 bytes {5} {6} [built]
| ./c.js 72 bytes [built]
| ./node_modules/z.js 20 bytes [built]
| ./c.js 72 bytes [built]
chunk {7} disabled/async-g.js (async-g) 54 bytes <{3}> <{4}> [rendered]
> ./g [] 6:0-47
> ./g [] 6:0-47
@ -228,8 +228,8 @@ Child default:
[2] ./node_modules/x.js 20 bytes {2} {3} {4} {5} [built]
[3] ./node_modules/y.js 20 bytes {2} {3} {6} [built]
[9] ./a.js + 1 modules 156 bytes {3} {12} [built]
| ./a.js 121 bytes [built]
| ./e.js 20 bytes [built]
| ./a.js 121 bytes [built]
chunk {4} default/c.js (c) 152 bytes [entry] [rendered]
> ./c c
[1] ./d.js 20 bytes {1} {2} {3} {4} [built]
@ -268,8 +268,8 @@ Child default:
chunk {12} default/async-a.js (async-a) 156 bytes <{0}> ={1}= ={5}= ={6}= >{8}< >{11}< [rendered]
> ./a [0] ./index.js 1:0-47
[9] ./a.js + 1 modules 156 bytes {3} {12} [built]
| ./a.js 121 bytes [built]
| ./e.js 20 bytes [built]
| ./a.js 121 bytes [built]
Child vendors:
Entrypoint main = vendors/main.js
Entrypoint a = vendors/vendors.js vendors/a.js
@ -291,8 +291,8 @@ Child vendors:
[2] ./node_modules/x.js 20 bytes {1} {2} {3} {7} [built]
[3] ./node_modules/y.js 20 bytes {1} {2} {7} [built]
[9] ./a.js + 1 modules 156 bytes {2} {6} [built]
| ./a.js 121 bytes [built]
| ./e.js 20 bytes [built]
| ./a.js 121 bytes [built]
chunk {3} vendors/async-c.js (async-c) 152 bytes <{0}> [rendered]
> ./c [0] ./index.js 3:0-47
[1] ./d.js 20 bytes {1} {2} {3} {4} {5} {6} [built]
@ -314,8 +314,8 @@ Child vendors:
> ./a a
[1] ./d.js 20 bytes {1} {2} {3} {4} {5} {6} [built]
[9] ./a.js + 1 modules 156 bytes {2} {6} [built]
| ./a.js 121 bytes [built]
| ./e.js 20 bytes [built]
| ./a.js 121 bytes [built]
chunk {7} vendors/vendors.js (vendors) 60 bytes ={4}= ={5}= ={6}= >{8}< [initial] [rendered] split chunk (cache group: vendors) (name: vendors)
> ./a a
> ./b b
@ -389,13 +389,13 @@ Child multiple-vendors:
chunk {11} multiple-vendors/a.js (a) 156 bytes ={1}= ={2}= ={3}= >{6}< >{10}< [entry] [rendered]
> ./a a
[9] ./a.js + 1 modules 156 bytes {11} {12} [built]
| ./a.js 121 bytes [built]
| ./e.js 20 bytes [built]
| ./a.js 121 bytes [built]
chunk {12} multiple-vendors/async-a.js (async-a) 156 bytes <{0}> ={1}= ={2}= ={3}= >{6}< >{10}< [rendered]
> ./a [0] ./index.js 1:0-47
[9] ./a.js + 1 modules 156 bytes {11} {12} [built]
| ./a.js 121 bytes [built]
| ./e.js 20 bytes [built]
| ./a.js 121 bytes [built]
Child all:
Entrypoint main = all/main.js
Entrypoint a = all/vendors~a~async-a~async-b~async-c~b~c.js all/vendors~a~async-a~async-b~b.js all/a~async-a~async-b~async-c~b~c.js all/a.js
@ -457,13 +457,13 @@ Child all:
chunk {11} all/a.js (a) 156 bytes ={1}= ={2}= ={3}= >{6}< >{10}< [entry] [rendered]
> ./a a
[9] ./a.js + 1 modules 156 bytes {11} {12} [built]
| ./a.js 121 bytes [built]
| ./e.js 20 bytes [built]
| ./a.js 121 bytes [built]
chunk {12} all/async-a.js (async-a) 156 bytes <{0}> ={1}= ={2}= ={3}= >{6}< >{10}< [rendered]
> ./a [0] ./index.js 1:0-47
[9] ./a.js + 1 modules 156 bytes {11} {12} [built]
| ./a.js 121 bytes [built]
| ./e.js 20 bytes [built]"
| ./e.js 20 bytes [built]
| ./a.js 121 bytes [built]"
`;
exports[`StatsTestCases should print correct stats for chunk-module-id-range 1`] = `
@ -505,28 +505,28 @@ chunk {0} bundle.js (main) 73 bytes >{1}< >{2}< [entry] [rendered]
> ./index main
[0] ./index.js 51 bytes {0} [built]
entry ./index main
factory:Xms building:Xms = Xms
Xms (resolving: Xms, building: Xms)
[1] ./a.js 22 bytes {0} [built]
cjs require ./a [0] ./index.js 1:0-14
[0] Xms -> factory:Xms building:Xms = Xms
[0] Xms -> Xms (resolving: Xms, building: Xms)
chunk {1} 1.bundle.js 22 bytes <{0}> [rendered]
> ./b [0] ./index.js 2:0-16
[2] ./b.js 22 bytes {1} [built]
amd require ./b [0] ./index.js 2:0-16
[0] Xms -> factory:Xms building:Xms = Xms
[0] Xms -> Xms (resolving: Xms, building: Xms)
chunk {2} 2.bundle.js 54 bytes <{0}> >{3}< [rendered]
> ./c [0] ./index.js 3:0-16
[3] ./c.js 54 bytes {2} [built]
amd require ./c [0] ./index.js 3:0-16
[0] Xms -> factory:Xms building:Xms = Xms
[0] Xms -> Xms (resolving: Xms, building: Xms)
chunk {3} 3.bundle.js 44 bytes <{2}> [rendered]
> [3] ./c.js 1:0-52
[4] ./d.js 22 bytes {3} [built]
require.ensure item ./d [3] ./c.js 1:0-52
[0] Xms -> [3] Xms -> factory:Xms building:Xms = Xms
[0] Xms -> [3] Xms -> Xms (resolving: Xms, building: Xms)
[5] ./e.js 22 bytes {3} [built]
require.ensure item ./e [3] ./c.js 1:0-52
[0] Xms -> [3] Xms -> factory:Xms building:Xms = Xms"
[0] Xms -> [3] Xms -> Xms (resolving: Xms, building: Xms)"
`;
exports[`StatsTestCases should print correct stats for chunks-development 1`] = `
@ -543,29 +543,29 @@ chunk {0} 0.bundle.js 22 bytes <{main}> [rendered]
> ./b [./index.js] ./index.js 2:0-16
[./b.js] 22 bytes {0} [built]
amd require ./b [./index.js] 2:0-16
[./index.js] Xms -> factory:Xms building:Xms = Xms
[./index.js] Xms -> Xms (resolving: Xms, building: Xms)
chunk {1} 1.bundle.js 54 bytes <{main}> >{2}< [rendered]
> ./c [./index.js] ./index.js 3:0-16
[./c.js] 54 bytes {1} [built]
amd require ./c [./index.js] 3:0-16
[./index.js] Xms -> factory:Xms building:Xms = Xms
[./index.js] Xms -> Xms (resolving: Xms, building: Xms)
chunk {2} 2.bundle.js 60 bytes <{1}> [rendered]
> [./c.js] ./c.js 1:0-52
[./d.js] 22 bytes {2} [built]
require.ensure item ./d [./c.js] 1:0-52
[./index.js] Xms -> [./c.js] Xms -> factory:Xms building:Xms = Xms
[./index.js] Xms -> [./c.js] Xms -> Xms (resolving: Xms, building: Xms)
[./e.js] 38 bytes {2} [built]
require.ensure item ./e [./c.js] 1:0-52
[./index.js] Xms -> [./c.js] Xms -> factory:Xms building:Xms = Xms
[./index.js] Xms -> [./c.js] Xms -> Xms (resolving: Xms, building: Xms)
chunk {main} bundle.js (main) 73 bytes >{0}< >{1}< [entry] [rendered]
> ./index main
[./a.js] 22 bytes {main} [built]
cjs require ./a [./e.js] 1:0-14
cjs require ./a [./index.js] 1:0-14
[./index.js] Xms -> factory:Xms building:Xms = Xms
[./index.js] Xms -> Xms (resolving: Xms, building: Xms)
[./index.js] 51 bytes {main} [built]
entry ./index main
factory:Xms building:Xms = Xms"
Xms (resolving: Xms, building: Xms)"
`;
exports[`StatsTestCases should print correct stats for circular-correctness 1`] = `
@ -656,9 +656,9 @@ Child
Entrypoint app = vendor.js app.js
[./constants.js] 87 bytes {0} [built]
[./entry-1.js] ./entry-1.js + 2 modules 190 bytes {1} [built]
| ./entry-1.js 67 bytes [built]
| ./submodule-a.js 59 bytes [built]
| ./submodule-b.js 59 bytes [built]
| ./entry-1.js 67 bytes [built]
Child
Hash: 5d578fbbda31da1fdadb
Time: Xms
@ -669,16 +669,16 @@ Child
Entrypoint app = vendor.js app.js
[./constants.js] 87 bytes {0} [built]
[./entry-2.js] ./entry-2.js + 2 modules 197 bytes {1} [built]
| ./entry-2.js 67 bytes [built]
| ./submodule-a.js 59 bytes [built]
| ./submodule-c.js 66 bytes [built]"
| ./submodule-c.js 66 bytes [built]
| ./entry-2.js 67 bytes [built]"
`;
exports[`StatsTestCases should print correct stats for concat-and-sideeffects 1`] = `
"[0] ./index.js + 2 modules 119 bytes {0} [built]
| ./index.js 46 bytes [built]
| ./node_modules/pmodule/a.js 49 bytes [built]
| ./node_modules/pmodule/aa.js 24 bytes [built]
| ./node_modules/pmodule/a.js 49 bytes [built]
| ./index.js 46 bytes [built]
./node_modules/pmodule/index.js 63 bytes [orphan] [built]
ModuleConcatenation bailout: Module is not in any chunk
./node_modules/pmodule/b.js 49 bytes [orphan] [built]
@ -1275,14 +1275,14 @@ Entrypoint main = main.js
[1] ./a.js?1 33 bytes {0} [built]
[2] ./c.js?1 33 bytes {0} [built]
[4] ./a.js?2 33 bytes {0} [built]
[5] ./c.js?2 33 bytes {0} [built]
[7] ./a.js?3 33 bytes {0} [built]
[8] ./c.js?3 33 bytes {0} [built]
[10] ./a.js?4 33 bytes {0} [built]
[11] ./c.js?4 33 bytes {0} [built]
[13] ./a.js?5 33 bytes {0} [built]
[14] ./c.js?5 33 bytes {0} [built]
[16] ./a.js?6 33 bytes {0} [built]
[17] ./c.js?6 33 bytes {0} [built]
[19] ./a.js?7 33 bytes {0} [built]
[20] ./c.js?7 33 bytes {0} [built]
[22] ./a.js?8 33 bytes {0} [built]
[25] ./a.js?9 33 bytes {0} [built]
[28] ./a.js?10 33 bytes {0} [built]
@ -1577,8 +1577,8 @@ main.js 4.01 KiB 0 main
Entrypoint main = main.js
[0] ./b.js 169 bytes {0} [built] [failed] [1 error]
[1] ./index.js + 1 modules 35 bytes {0} [built]
| ./index.js 15 bytes [built]
| ./a.js 15 bytes [built]
| ./index.js 15 bytes [built]
ERROR in ./b.js 6:7
Module parse failed: Unexpected token (6:7)
@ -2025,33 +2025,33 @@ chunk {0} main.js (main) 73 bytes >{1}< >{2}< [entry] [rendered]
[0] ./index.js 51 bytes {0} [depth 0] [built]
ModuleConcatenation bailout: Module is not an ECMAScript module
entry ./index main
factory:Xms building:Xms = Xms
Xms (resolving: Xms, building: Xms)
[1] ./a.js 22 bytes {0} [depth 1] [built]
ModuleConcatenation bailout: Module is not an ECMAScript module
cjs require ./a [0] ./index.js 1:0-14
[0] Xms -> factory:Xms building:Xms = Xms
[0] Xms -> Xms (resolving: Xms, building: Xms)
chunk {1} 1.js 22 bytes <{0}> [rendered]
> ./b [0] ./index.js 2:0-16
[2] ./b.js 22 bytes {1} [depth 1] [built]
ModuleConcatenation bailout: Module is not an ECMAScript module
amd require ./b [0] ./index.js 2:0-16
[0] Xms -> factory:Xms building:Xms = Xms
[0] Xms -> Xms (resolving: Xms, building: Xms)
chunk {2} 2.js 54 bytes <{0}> >{3}< [rendered]
> ./c [0] ./index.js 3:0-16
[3] ./c.js 54 bytes {2} [depth 1] [built]
ModuleConcatenation bailout: Module is not an ECMAScript module
amd require ./c [0] ./index.js 3:0-16
[0] Xms -> factory:Xms building:Xms = Xms
[0] Xms -> Xms (resolving: Xms, building: Xms)
chunk {3} 3.js 44 bytes <{2}> [rendered]
> [3] ./c.js 1:0-52
[4] ./d.js 22 bytes {3} [depth 2] [built]
ModuleConcatenation bailout: Module is not an ECMAScript module
require.ensure item ./d [3] ./c.js 1:0-52
[0] Xms -> [3] Xms -> factory:Xms building:Xms = Xms
[0] Xms -> [3] Xms -> Xms (resolving: Xms, building: Xms)
[5] ./e.js 22 bytes {3} [depth 2] [built]
ModuleConcatenation bailout: Module is not an ECMAScript module
require.ensure item ./e [3] ./c.js 1:0-52
[0] Xms -> [3] Xms -> factory:Xms building:Xms = Xms"
[0] Xms -> [3] Xms -> Xms (resolving: Xms, building: Xms)"
`;
exports[`StatsTestCases should print correct stats for resolve-plugin-context 1`] = `
@ -2164,9 +2164,9 @@ Entrypoint entry = entry.js
ModuleConcatenation bailout: Module is not an ECMAScript module
[8] ./concatenated.js + 2 modules 116 bytes {2} [built]
ModuleConcatenation bailout: Cannot concat with external \\"external\\" (<- Module is not an ECMAScript module)
| ./concatenated.js 26 bytes [built]
| ./concatenated2.js 48 bytes [built]
| ./concatenated1.js 37 bytes [built]
| ./concatenated2.js 48 bytes [built]"
| ./concatenated.js 26 bytes [built]"
`;
exports[`StatsTestCases should print correct stats for scope-hoisting-multi 1`] = `
@ -2211,11 +2211,11 @@ Child
[7] ./first.js + 1 modules 248 bytes {5} [built]
ModuleConcatenation bailout: Cannot concat with ./common.js (<- Module is referenced from different chunks by these modules: ./first.js + 1 modules, ./second.js)
ModuleConcatenation bailout: Cannot concat with ./vendor.js (<- Module is referenced from different chunks by these modules: ./first.js + 1 modules, ./second.js)
| ./first.js 207 bytes [built]
| ./module_first.js 31 bytes [built]
| ./first.js 207 bytes [built]
[8] ./common.js + 1 modules 62 bytes {1} {5} [built]
| ./common.js 37 bytes [built]
| ./common2.js 25 bytes [built]"
| ./common2.js 25 bytes [built]
| ./common.js 37 bytes [built]"
`;
exports[`StatsTestCases should print correct stats for side-effects-issue-7428 1`] = `
@ -2243,10 +2243,10 @@ Entrypoint main = main.js
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
entry ./main.js main
| ./main.js 144 bytes [built]
| ./components/src/CompAB/CompB.js 77 bytes [built]
| [only some exports used: default]
| harmony import specifier ./components ./main.js 4:15-20 (skipped side-effect-free modules)
| ./main.js 144 bytes [built]
./components/src/index.js 84 bytes [orphan] [built]
[module unused]
harmony side effect evaluation ./components [2] ./foo.js 1:0-37
@ -2277,7 +2277,6 @@ Entrypoint main = main.js
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
entry ./index main
| ./index.js 55 bytes [built]
| ./node_modules/pmodule/index.js 75 bytes [built]
| [only some exports used: default]
| harmony side effect evaluation pmodule ./index.js 1:0-33
@ -2285,6 +2284,7 @@ Entrypoint main = main.js
| ./node_modules/pmodule/c.js 28 bytes [built]
| [only some exports used: z]
| harmony import specifier pmodule ./index.js 3:17-18 (skipped side-effect-free modules)
| ./index.js 55 bytes [built]
./node_modules/pmodule/a.js 60 bytes [orphan] [built]
[module unused]
harmony side effect evaluation ./a [0] ./index.js + 2 modules 1:0-20
@ -2316,7 +2316,7 @@ bundle.js 3.57 KiB 0 [emitted] main
Entrypoint main = bundle.js
[0] ./index.js 0 bytes {0} [built]
entry ./index main
factory:Xms building:Xms = Xms"
Xms (resolving: Xms, building: Xms)"
`;
exports[`StatsTestCases should print correct stats for split-chunks 1`] = `
@ -2346,8 +2346,8 @@ exports[`StatsTestCases should print correct stats for split-chunks 1`] = `
[2] ./node_modules/x.js 20 bytes {2} {3} {4} {5} [built]
[3] ./node_modules/y.js 20 bytes {2} {3} {6} [built]
[9] ./a.js + 1 modules 156 bytes {3} {12} [built]
| ./a.js 121 bytes [built]
| ./e.js 20 bytes [built]
| ./a.js 121 bytes [built]
chunk {4} default/c.js (c) 152 bytes [entry] [rendered]
> ./c c
[1] ./d.js 20 bytes {1} {2} {3} {4} [built]
@ -2386,8 +2386,8 @@ exports[`StatsTestCases should print correct stats for split-chunks 1`] = `
chunk {12} default/async-a.js (async-a) 156 bytes <{0}> ={1}= ={5}= ={6}= >{8}< >{11}< [rendered]
> ./a [0] ./index.js 1:0-47
[9] ./a.js + 1 modules 156 bytes {3} {12} [built]
| ./a.js 121 bytes [built]
| ./e.js 20 bytes [built]
| ./a.js 121 bytes [built]
Child all-chunks:
Entrypoint main = default/main.js
Entrypoint a = default/vendors~a~async-a~async-b~async-c~b~c.js default/vendors~a~async-a~async-b~b.js default/a~async-a~async-b~async-c~b~c.js default/a.js
@ -2449,13 +2449,13 @@ Child all-chunks:
chunk {11} default/a.js (a) 156 bytes ={1}= ={2}= ={3}= >{6}< >{10}< [entry] [rendered]
> ./a a
[9] ./a.js + 1 modules 156 bytes {11} {12} [built]
| ./a.js 121 bytes [built]
| ./e.js 20 bytes [built]
| ./a.js 121 bytes [built]
chunk {12} default/async-a.js (async-a) 156 bytes <{0}> ={1}= ={2}= ={3}= >{6}< >{10}< [rendered]
> ./a [0] ./index.js 1:0-47
[9] ./a.js + 1 modules 156 bytes {11} {12} [built]
| ./a.js 121 bytes [built]
| ./e.js 20 bytes [built]
| ./a.js 121 bytes [built]
Child manual:
Entrypoint main = default/main.js
Entrypoint a = default/vendors.js default/a.js
@ -2488,14 +2488,14 @@ Child manual:
> ./a a
[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]
| ./a.js 121 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]
[9] ./a.js + 1 modules 156 bytes {5} {6} [built]
| ./a.js 121 bytes [built]
| ./e.js 20 bytes [built]
| ./a.js 121 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
@ -2575,8 +2575,8 @@ Child name-too-long:
> ./a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
> ./a [0] ./index.js 1:0-47
[9] ./a.js + 1 modules 156 bytes {12} [built]
| ./a.js 121 bytes [built]
| ./e.js 20 bytes [built]
| ./a.js 121 bytes [built]
Child custom-chunks-filter:
Entrypoint main = default/main.js
Entrypoint a = default/a.js
@ -2598,8 +2598,8 @@ Child custom-chunks-filter:
[2] ./node_modules/x.js 20 bytes {2} {3} [built]
[3] ./node_modules/y.js 20 bytes {2} {4} [built]
[9] ./a.js + 1 modules 156 bytes {2} {12} [built]
| ./a.js 121 bytes [built]
| ./e.js 20 bytes [built]
| ./a.js 121 bytes [built]
chunk {3} default/vendors~async-a~async-b~async-c~b~c.js (vendors~async-a~async-b~async-c~b~c) 20 bytes <{0}> ={1}= ={4}= ={5}= ={6}= ={7}= ={8}= ={9}= ={10}= ={12}= >{7}< >{11}< [initial] [rendered] split chunk (cache group: defaultVendors) (name: vendors~async-a~async-b~async-c~b~c)
> ./b b
> ./c c
@ -2643,8 +2643,8 @@ Child custom-chunks-filter:
chunk {12} default/async-a.js (async-a) 156 bytes <{0}> ={1}= ={3}= ={4}= >{7}< >{11}< [rendered]
> ./a [0] ./index.js 1:0-47
[9] ./a.js + 1 modules 156 bytes {2} {12} [built]
| ./a.js 121 bytes [built]
| ./e.js 20 bytes [built]
| ./a.js 121 bytes [built]
Child custom-chunks-filter-in-cache-groups:
Entrypoint main = default/main.js
Entrypoint a = default/a.js
@ -2659,8 +2659,8 @@ 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]
[9] ./a.js + 1 modules 156 bytes {1} {6} [built]
| ./a.js 121 bytes [built]
| ./e.js 20 bytes [built]
| ./a.js 121 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]
@ -2685,8 +2685,8 @@ Child custom-chunks-filter-in-cache-groups:
> ./a [0] ./index.js 1:0-47
[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]
| ./a.js 121 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
@ -2734,8 +2734,8 @@ chunk {6} common~async-c.js (common~async-c) 20 bytes <{0}> ={1}= ={4}= ={5}=
chunk {7} async-a.js (async-a) 107 bytes <{0}> ={1}= ={2}= [rendered]
> ./a [0] ./index.js 1:0-47
[8] ./a.js + 1 modules 107 bytes {7} [built]
| ./a.js 72 bytes [built]
| ./e.js 20 bytes [built]"
| ./e.js 20 bytes [built]
| ./a.js 72 bytes [built]"
`;
exports[`StatsTestCases should print correct stats for split-chunks-combinations 1`] = `

View File

@ -0,0 +1,8 @@
module.exports = function() {
this.cacheable(false);
return new Promise(resolve => {
setTimeout(() => {
resolve("module.exports = require('./foo/' + WATCH_STEP);");
}, 500);
});
}

View File

@ -1,5 +1 @@
var a = require("./a");
var b = require("./b");
var c = require("./c");
module.exports = a + b + c + '.0';
module.exports = '0';

View File

@ -1,7 +1,10 @@
it("should watch for changes", function() {
expect(require("./foo/" + WATCH_STEP)).toBe('This is only a test.' + WATCH_STEP);
if(+WATCH_STEP !== 3)
expect(require("./delayed!./delayed")).toBe(WATCH_STEP);
else
expect(require("./delayed!./delayed")).toBe('This is only a test.' + WATCH_STEP);
if(+WATCH_STEP > 0) {
for(var m of STATS_JSON.modules.filter(m => /(a|b|c)\.js$/.test(m.identifier)))
expect(m.prefetched).toBe(true);
expect(m.issuer).toBe(null);
}
});

View File

@ -1,5 +1 @@
var a = require("./a");
var b = require("./b");
var c = require("./c");
module.exports = a + b + c + '.1';
module.exports = '1';

View File

@ -1,5 +1 @@
var a = require("./a");
var b = require("./b");
var c = require("./c");
module.exports = a + b + c + '.2';
module.exports = '2';