webpack 4.35.3 → 4.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/declarations/WebpackOptions.d.ts +36 -11
- package/lib/AbstractMethodError.js +43 -0
- package/lib/Chunk.js +5 -1
- package/lib/ChunkGroup.js +1 -1
- package/lib/Compilation.js +87 -471
- package/lib/Compiler.js +33 -0
- package/lib/HashedModuleIdsPlugin.js +3 -1
- package/lib/JavascriptModulesPlugin.js +2 -3
- package/lib/ModuleFilenameHelpers.js +2 -1
- package/lib/NamedModulesPlugin.js +2 -1
- package/lib/NormalModule.js +16 -5
- package/lib/NormalModuleFactory.js +2 -2
- package/lib/OptionsDefaulter.js +9 -9
- package/lib/ProgressPlugin.js +0 -1
- package/lib/ResolverFactory.js +11 -14
- package/lib/SourceMapDevToolPlugin.js +110 -22
- package/lib/Stats.js +221 -3
- package/lib/Template.js +1 -1
- package/lib/TemplatedPathPlugin.js +4 -1
- package/lib/WebpackOptionsApply.js +5 -6
- package/lib/WebpackOptionsDefaulter.js +12 -1
- package/lib/buildChunkGraph.js +689 -0
- package/lib/debug/ProfilingPlugin.js +1 -1
- package/lib/logging/Logger.js +126 -0
- package/lib/logging/createConsoleLogger.js +188 -0
- package/lib/logging/runtime.js +35 -0
- package/lib/node/NodeEnvironmentPlugin.js +14 -0
- package/lib/util/cleverMerge.js +77 -0
- package/lib/util/createHash.js +57 -12
- package/lib/util/objectToMap.js +1 -1
- package/lib/wasm/WebAssemblyGenerator.js +7 -7
- package/lib/webpack.js +3 -1
- package/package.json +2 -1
- package/schemas/WebpackOptions.json +54 -2
package/lib/Compilation.js
CHANGED
@@ -27,15 +27,16 @@ const HotUpdateChunkTemplate = require("./HotUpdateChunkTemplate");
|
|
27
27
|
const ModuleTemplate = require("./ModuleTemplate");
|
28
28
|
const RuntimeTemplate = require("./RuntimeTemplate");
|
29
29
|
const ChunkRenderError = require("./ChunkRenderError");
|
30
|
-
const AsyncDependencyToInitialChunkError = require("./AsyncDependencyToInitialChunkError");
|
31
30
|
const Stats = require("./Stats");
|
32
31
|
const Semaphore = require("./util/Semaphore");
|
33
32
|
const createHash = require("./util/createHash");
|
34
|
-
const Queue = require("./util/Queue");
|
35
33
|
const SortableSet = require("./util/SortableSet");
|
36
34
|
const GraphHelpers = require("./GraphHelpers");
|
37
35
|
const ModuleDependency = require("./dependencies/ModuleDependency");
|
38
36
|
const compareLocations = require("./compareLocations");
|
37
|
+
const { Logger, LogType } = require("./logging/Logger");
|
38
|
+
const ErrorHelpers = require("./ErrorHelpers");
|
39
|
+
const buildChunkGraph = require("./buildChunkGraph");
|
39
40
|
|
40
41
|
/** @typedef {import("./Module")} Module */
|
41
42
|
/** @typedef {import("./Compiler")} Compiler */
|
@@ -95,6 +96,14 @@ const compareLocations = require("./compareLocations");
|
|
95
96
|
* @property {DependenciesBlockVariable[]} variables
|
96
97
|
*/
|
97
98
|
|
99
|
+
/**
|
100
|
+
* @typedef {Object} LogEntry
|
101
|
+
* @property {string} type
|
102
|
+
* @property {any[]} args
|
103
|
+
* @property {number} time
|
104
|
+
* @property {string[]=} trace
|
105
|
+
*/
|
106
|
+
|
98
107
|
/**
|
99
108
|
* @param {Chunk} a first chunk to sort by id
|
100
109
|
* @param {Chunk} b second chunk to sort by id
|
@@ -155,16 +164,6 @@ const byNameOrHash = (a, b) => {
|
|
155
164
|
return 0;
|
156
165
|
};
|
157
166
|
|
158
|
-
/**
|
159
|
-
* @template T
|
160
|
-
* @param {Set<T>} a first set
|
161
|
-
* @param {Set<T>} b second set
|
162
|
-
* @returns {number} cmp
|
163
|
-
*/
|
164
|
-
const bySetSize = (a, b) => {
|
165
|
-
return a.size - b.size;
|
166
|
-
};
|
167
|
-
|
168
167
|
/**
|
169
168
|
* @param {DependenciesBlockVariable[]} variables DepBlock Variables to iterate over
|
170
169
|
* @param {DepBlockVarDependenciesCallback} fn callback to apply on iterated elements
|
@@ -384,6 +383,9 @@ class Compilation extends Tapable {
|
|
384
383
|
"compilerIndex"
|
385
384
|
]),
|
386
385
|
|
386
|
+
/** @type {SyncBailHook<string, LogEntry>} */
|
387
|
+
log: new SyncBailHook(["origin", "logEntry"]),
|
388
|
+
|
387
389
|
// TODO the following hooks are weirdly located here
|
388
390
|
// TODO move them for webpack 5
|
389
391
|
/** @type {SyncHook<object, Module>} */
|
@@ -469,6 +471,8 @@ class Compilation extends Tapable {
|
|
469
471
|
this.warnings = [];
|
470
472
|
/** @type {Compilation[]} */
|
471
473
|
this.children = [];
|
474
|
+
/** @type {Map<string, LogEntry[]>} */
|
475
|
+
this.logging = new Map();
|
472
476
|
/** @type {Map<DepConstructor, ModuleFactory>} */
|
473
477
|
this.dependencyFactories = new Map();
|
474
478
|
/** @type {Map<DepConstructor, DependencyTemplate>} */
|
@@ -499,6 +503,69 @@ class Compilation extends Tapable {
|
|
499
503
|
return new Stats(this);
|
500
504
|
}
|
501
505
|
|
506
|
+
/**
|
507
|
+
* @param {string | (function(): string)} name name of the logger, or function called once to get the logger name
|
508
|
+
* @returns {Logger} a logger with that name
|
509
|
+
*/
|
510
|
+
getLogger(name) {
|
511
|
+
if (!name) {
|
512
|
+
throw new TypeError("Compilation.getLogger(name) called without a name");
|
513
|
+
}
|
514
|
+
/** @type {LogEntry[] | undefined} */
|
515
|
+
let logEntries;
|
516
|
+
return new Logger((type, args) => {
|
517
|
+
if (typeof name === "function") {
|
518
|
+
name = name();
|
519
|
+
if (!name) {
|
520
|
+
throw new TypeError(
|
521
|
+
"Compilation.getLogger(name) called with a function not returning a name"
|
522
|
+
);
|
523
|
+
}
|
524
|
+
}
|
525
|
+
let trace;
|
526
|
+
switch (type) {
|
527
|
+
case LogType.warn:
|
528
|
+
case LogType.error:
|
529
|
+
case LogType.trace:
|
530
|
+
trace = ErrorHelpers.cutOffLoaderExecution(new Error("Trace").stack)
|
531
|
+
.split("\n")
|
532
|
+
.slice(3);
|
533
|
+
break;
|
534
|
+
}
|
535
|
+
/** @type {LogEntry} */
|
536
|
+
const logEntry = {
|
537
|
+
time: Date.now(),
|
538
|
+
type,
|
539
|
+
args,
|
540
|
+
trace
|
541
|
+
};
|
542
|
+
if (this.hooks.log.call(name, logEntry) === undefined) {
|
543
|
+
if (logEntry.type === LogType.profileEnd) {
|
544
|
+
// eslint-disable-next-line node/no-unsupported-features/node-builtins
|
545
|
+
if (typeof console.profileEnd === "function") {
|
546
|
+
// eslint-disable-next-line node/no-unsupported-features/node-builtins
|
547
|
+
console.profileEnd(`[${name}] ${logEntry.args[0]}`);
|
548
|
+
}
|
549
|
+
}
|
550
|
+
if (logEntries === undefined) {
|
551
|
+
logEntries = this.logging.get(name);
|
552
|
+
if (logEntries === undefined) {
|
553
|
+
logEntries = [];
|
554
|
+
this.logging.set(name, logEntries);
|
555
|
+
}
|
556
|
+
}
|
557
|
+
logEntries.push(logEntry);
|
558
|
+
if (logEntry.type === LogType.profile) {
|
559
|
+
// eslint-disable-next-line node/no-unsupported-features/node-builtins
|
560
|
+
if (typeof console.profile === "function") {
|
561
|
+
// eslint-disable-next-line node/no-unsupported-features/node-builtins
|
562
|
+
console.profile(`[${name}] ${logEntry.args[0]}`);
|
563
|
+
}
|
564
|
+
}
|
565
|
+
}
|
566
|
+
});
|
567
|
+
}
|
568
|
+
|
502
569
|
/**
|
503
570
|
* @typedef {Object} AddModuleResult
|
504
571
|
* @property {Module} module the added or existing module
|
@@ -1217,7 +1284,10 @@ class Compilation extends Tapable {
|
|
1217
1284
|
|
1218
1285
|
this.assignDepth(module);
|
1219
1286
|
}
|
1220
|
-
|
1287
|
+
buildChunkGraph(
|
1288
|
+
this,
|
1289
|
+
/** @type {Entrypoint[]} */ (this.chunkGroups.slice())
|
1290
|
+
);
|
1221
1291
|
this.sortModules(this.modules);
|
1222
1292
|
this.hooks.afterChunks.call(this.chunks);
|
1223
1293
|
|
@@ -1505,460 +1575,6 @@ class Compilation extends Tapable {
|
|
1505
1575
|
return this.hooks.dependencyReference.call(ref, dependency, module);
|
1506
1576
|
}
|
1507
1577
|
|
1508
|
-
/**
|
1509
|
-
* This method creates the Chunk graph from the Module graph
|
1510
|
-
* @private
|
1511
|
-
* @param {TODO[]} inputChunkGroups chunk groups which are processed
|
1512
|
-
* @returns {void}
|
1513
|
-
*/
|
1514
|
-
processDependenciesBlocksForChunkGroups(inputChunkGroups) {
|
1515
|
-
// Process is splitting into two parts:
|
1516
|
-
// Part one traverse the module graph and builds a very basic chunks graph
|
1517
|
-
// in chunkDependencies.
|
1518
|
-
// Part two traverse every possible way through the basic chunk graph and
|
1519
|
-
// tracks the available modules. While traversing it connects chunks with
|
1520
|
-
// eachother and Blocks with Chunks. It stops traversing when all modules
|
1521
|
-
// for a chunk are already available. So it doesn't connect unneeded chunks.
|
1522
|
-
|
1523
|
-
/** @type {Map<ChunkGroup, {block: AsyncDependenciesBlock, chunkGroup: ChunkGroup, couldBeFiltered: boolean}[]>} */
|
1524
|
-
const chunkDependencies = new Map();
|
1525
|
-
const allCreatedChunkGroups = new Set();
|
1526
|
-
|
1527
|
-
// PREPARE
|
1528
|
-
/** @type {Map<DependenciesBlock, { modules: Module[], blocks: AsyncDependenciesBlock[]}>} */
|
1529
|
-
const blockInfoMap = new Map();
|
1530
|
-
|
1531
|
-
/**
|
1532
|
-
* @param {Dependency} d dependency to iterate over
|
1533
|
-
* @returns {void}
|
1534
|
-
*/
|
1535
|
-
const iteratorDependency = d => {
|
1536
|
-
// We skip Dependencies without Reference
|
1537
|
-
const ref = this.getDependencyReference(currentModule, d);
|
1538
|
-
if (!ref) {
|
1539
|
-
return;
|
1540
|
-
}
|
1541
|
-
// We skip Dependencies without Module pointer
|
1542
|
-
const refModule = ref.module;
|
1543
|
-
if (!refModule) {
|
1544
|
-
return;
|
1545
|
-
}
|
1546
|
-
// We skip weak Dependencies
|
1547
|
-
if (ref.weak) {
|
1548
|
-
return;
|
1549
|
-
}
|
1550
|
-
|
1551
|
-
blockInfoModules.add(refModule);
|
1552
|
-
};
|
1553
|
-
|
1554
|
-
/**
|
1555
|
-
* @param {AsyncDependenciesBlock} b blocks to prepare
|
1556
|
-
* @returns {void}
|
1557
|
-
*/
|
1558
|
-
const iteratorBlockPrepare = b => {
|
1559
|
-
blockInfoBlocks.push(b);
|
1560
|
-
blockQueue.push(b);
|
1561
|
-
};
|
1562
|
-
|
1563
|
-
/** @type {Module} */
|
1564
|
-
let currentModule;
|
1565
|
-
/** @type {DependenciesBlock} */
|
1566
|
-
let block;
|
1567
|
-
/** @type {DependenciesBlock[]} */
|
1568
|
-
let blockQueue;
|
1569
|
-
/** @type {Set<Module>} */
|
1570
|
-
let blockInfoModules;
|
1571
|
-
/** @type {AsyncDependenciesBlock[]} */
|
1572
|
-
let blockInfoBlocks;
|
1573
|
-
|
1574
|
-
for (const module of this.modules) {
|
1575
|
-
blockQueue = [module];
|
1576
|
-
currentModule = module;
|
1577
|
-
while (blockQueue.length > 0) {
|
1578
|
-
block = blockQueue.pop();
|
1579
|
-
blockInfoModules = new Set();
|
1580
|
-
blockInfoBlocks = [];
|
1581
|
-
|
1582
|
-
if (block.variables) {
|
1583
|
-
iterationBlockVariable(block.variables, iteratorDependency);
|
1584
|
-
}
|
1585
|
-
|
1586
|
-
if (block.dependencies) {
|
1587
|
-
iterationOfArrayCallback(block.dependencies, iteratorDependency);
|
1588
|
-
}
|
1589
|
-
|
1590
|
-
if (block.blocks) {
|
1591
|
-
iterationOfArrayCallback(block.blocks, iteratorBlockPrepare);
|
1592
|
-
}
|
1593
|
-
|
1594
|
-
const blockInfo = {
|
1595
|
-
modules: Array.from(blockInfoModules),
|
1596
|
-
blocks: blockInfoBlocks
|
1597
|
-
};
|
1598
|
-
blockInfoMap.set(block, blockInfo);
|
1599
|
-
}
|
1600
|
-
}
|
1601
|
-
|
1602
|
-
// PART ONE
|
1603
|
-
|
1604
|
-
/** @type {Map<ChunkGroup, { index: number, index2: number }>} */
|
1605
|
-
const chunkGroupCounters = new Map();
|
1606
|
-
for (const chunkGroup of inputChunkGroups) {
|
1607
|
-
chunkGroupCounters.set(chunkGroup, { index: 0, index2: 0 });
|
1608
|
-
}
|
1609
|
-
|
1610
|
-
let nextFreeModuleIndex = 0;
|
1611
|
-
let nextFreeModuleIndex2 = 0;
|
1612
|
-
|
1613
|
-
/** @type {Map<DependenciesBlock, ChunkGroup>} */
|
1614
|
-
const blockChunkGroups = new Map();
|
1615
|
-
|
1616
|
-
/** @type {Set<DependenciesBlock>} */
|
1617
|
-
const blocksWithNestedBlocks = new Set();
|
1618
|
-
|
1619
|
-
const ADD_AND_ENTER_MODULE = 0;
|
1620
|
-
const ENTER_MODULE = 1;
|
1621
|
-
const PROCESS_BLOCK = 2;
|
1622
|
-
const LEAVE_MODULE = 3;
|
1623
|
-
|
1624
|
-
/**
|
1625
|
-
* @typedef {Object} QueueItem
|
1626
|
-
* @property {number} action
|
1627
|
-
* @property {DependenciesBlock} block
|
1628
|
-
* @property {Module} module
|
1629
|
-
* @property {Chunk} chunk
|
1630
|
-
* @property {ChunkGroup} chunkGroup
|
1631
|
-
*/
|
1632
|
-
|
1633
|
-
/**
|
1634
|
-
* @param {ChunkGroup} chunkGroup chunk group
|
1635
|
-
* @returns {QueueItem} queue item
|
1636
|
-
*/
|
1637
|
-
const chunkGroupToQueueItem = chunkGroup => ({
|
1638
|
-
action: ENTER_MODULE,
|
1639
|
-
block: chunkGroup.chunks[0].entryModule,
|
1640
|
-
module: chunkGroup.chunks[0].entryModule,
|
1641
|
-
chunk: chunkGroup.chunks[0],
|
1642
|
-
chunkGroup
|
1643
|
-
});
|
1644
|
-
|
1645
|
-
// Start with the provided modules/chunks
|
1646
|
-
/** @type {QueueItem[]} */
|
1647
|
-
let queue = inputChunkGroups.map(chunkGroupToQueueItem).reverse();
|
1648
|
-
/** @type {QueueItem[]} */
|
1649
|
-
let queueDelayed = [];
|
1650
|
-
|
1651
|
-
/** @type {Module} */
|
1652
|
-
let module;
|
1653
|
-
/** @type {Chunk} */
|
1654
|
-
let chunk;
|
1655
|
-
/** @type {ChunkGroup} */
|
1656
|
-
let chunkGroup;
|
1657
|
-
|
1658
|
-
// For each async Block in graph
|
1659
|
-
/**
|
1660
|
-
* @param {AsyncDependenciesBlock} b iterating over each Async DepBlock
|
1661
|
-
* @returns {void}
|
1662
|
-
*/
|
1663
|
-
const iteratorBlock = b => {
|
1664
|
-
// 1. We create a chunk for this Block
|
1665
|
-
// but only once (blockChunkGroups map)
|
1666
|
-
let c = blockChunkGroups.get(b);
|
1667
|
-
if (c === undefined) {
|
1668
|
-
c = this.namedChunkGroups.get(b.chunkName);
|
1669
|
-
if (c && c.isInitial()) {
|
1670
|
-
this.errors.push(
|
1671
|
-
new AsyncDependencyToInitialChunkError(b.chunkName, module, b.loc)
|
1672
|
-
);
|
1673
|
-
c = chunkGroup;
|
1674
|
-
} else {
|
1675
|
-
c = this.addChunkInGroup(
|
1676
|
-
b.groupOptions || b.chunkName,
|
1677
|
-
module,
|
1678
|
-
b.loc,
|
1679
|
-
b.request
|
1680
|
-
);
|
1681
|
-
chunkGroupCounters.set(c, { index: 0, index2: 0 });
|
1682
|
-
blockChunkGroups.set(b, c);
|
1683
|
-
allCreatedChunkGroups.add(c);
|
1684
|
-
}
|
1685
|
-
} else {
|
1686
|
-
// TODO webpack 5 remove addOptions check
|
1687
|
-
if (c.addOptions) c.addOptions(b.groupOptions);
|
1688
|
-
c.addOrigin(module, b.loc, b.request);
|
1689
|
-
}
|
1690
|
-
|
1691
|
-
// 2. We store the Block+Chunk mapping as dependency for the chunk
|
1692
|
-
let deps = chunkDependencies.get(chunkGroup);
|
1693
|
-
if (!deps) chunkDependencies.set(chunkGroup, (deps = []));
|
1694
|
-
deps.push({
|
1695
|
-
block: b,
|
1696
|
-
chunkGroup: c,
|
1697
|
-
couldBeFiltered: true
|
1698
|
-
});
|
1699
|
-
|
1700
|
-
// 3. We enqueue the DependenciesBlock for traversal
|
1701
|
-
queueDelayed.push({
|
1702
|
-
action: PROCESS_BLOCK,
|
1703
|
-
block: b,
|
1704
|
-
module: module,
|
1705
|
-
chunk: c.chunks[0],
|
1706
|
-
chunkGroup: c
|
1707
|
-
});
|
1708
|
-
};
|
1709
|
-
|
1710
|
-
// Iterative traversal of the Module graph
|
1711
|
-
// Recursive would be simpler to write but could result in Stack Overflows
|
1712
|
-
while (queue.length) {
|
1713
|
-
while (queue.length) {
|
1714
|
-
const queueItem = queue.pop();
|
1715
|
-
module = queueItem.module;
|
1716
|
-
block = queueItem.block;
|
1717
|
-
chunk = queueItem.chunk;
|
1718
|
-
chunkGroup = queueItem.chunkGroup;
|
1719
|
-
|
1720
|
-
switch (queueItem.action) {
|
1721
|
-
case ADD_AND_ENTER_MODULE: {
|
1722
|
-
// We connect Module and Chunk when not already done
|
1723
|
-
if (chunk.addModule(module)) {
|
1724
|
-
module.addChunk(chunk);
|
1725
|
-
} else {
|
1726
|
-
// already connected, skip it
|
1727
|
-
break;
|
1728
|
-
}
|
1729
|
-
}
|
1730
|
-
// fallthrough
|
1731
|
-
case ENTER_MODULE: {
|
1732
|
-
if (chunkGroup !== undefined) {
|
1733
|
-
const index = chunkGroup.getModuleIndex(module);
|
1734
|
-
if (index === undefined) {
|
1735
|
-
chunkGroup.setModuleIndex(
|
1736
|
-
module,
|
1737
|
-
chunkGroupCounters.get(chunkGroup).index++
|
1738
|
-
);
|
1739
|
-
}
|
1740
|
-
}
|
1741
|
-
|
1742
|
-
if (module.index === null) {
|
1743
|
-
module.index = nextFreeModuleIndex++;
|
1744
|
-
}
|
1745
|
-
|
1746
|
-
queue.push({
|
1747
|
-
action: LEAVE_MODULE,
|
1748
|
-
block,
|
1749
|
-
module,
|
1750
|
-
chunk,
|
1751
|
-
chunkGroup
|
1752
|
-
});
|
1753
|
-
}
|
1754
|
-
// fallthrough
|
1755
|
-
case PROCESS_BLOCK: {
|
1756
|
-
// get prepared block info
|
1757
|
-
const blockInfo = blockInfoMap.get(block);
|
1758
|
-
|
1759
|
-
// Traverse all referenced modules
|
1760
|
-
for (let i = blockInfo.modules.length - 1; i >= 0; i--) {
|
1761
|
-
const refModule = blockInfo.modules[i];
|
1762
|
-
if (chunk.containsModule(refModule)) {
|
1763
|
-
// skip early if already connected
|
1764
|
-
continue;
|
1765
|
-
}
|
1766
|
-
// enqueue the add and enter to enter in the correct order
|
1767
|
-
// this is relevant with circular dependencies
|
1768
|
-
queue.push({
|
1769
|
-
action: ADD_AND_ENTER_MODULE,
|
1770
|
-
block: refModule,
|
1771
|
-
module: refModule,
|
1772
|
-
chunk,
|
1773
|
-
chunkGroup
|
1774
|
-
});
|
1775
|
-
}
|
1776
|
-
|
1777
|
-
// Traverse all Blocks
|
1778
|
-
iterationOfArrayCallback(blockInfo.blocks, iteratorBlock);
|
1779
|
-
|
1780
|
-
if (blockInfo.blocks.length > 0 && module !== block) {
|
1781
|
-
blocksWithNestedBlocks.add(block);
|
1782
|
-
}
|
1783
|
-
break;
|
1784
|
-
}
|
1785
|
-
case LEAVE_MODULE: {
|
1786
|
-
if (chunkGroup !== undefined) {
|
1787
|
-
const index = chunkGroup.getModuleIndex2(module);
|
1788
|
-
if (index === undefined) {
|
1789
|
-
chunkGroup.setModuleIndex2(
|
1790
|
-
module,
|
1791
|
-
chunkGroupCounters.get(chunkGroup).index2++
|
1792
|
-
);
|
1793
|
-
}
|
1794
|
-
}
|
1795
|
-
|
1796
|
-
if (module.index2 === null) {
|
1797
|
-
module.index2 = nextFreeModuleIndex2++;
|
1798
|
-
}
|
1799
|
-
break;
|
1800
|
-
}
|
1801
|
-
}
|
1802
|
-
}
|
1803
|
-
const tempQueue = queue;
|
1804
|
-
queue = queueDelayed.reverse();
|
1805
|
-
queueDelayed = tempQueue;
|
1806
|
-
}
|
1807
|
-
|
1808
|
-
// PART TWO
|
1809
|
-
/** @type {Set<Module>} */
|
1810
|
-
let newAvailableModules;
|
1811
|
-
|
1812
|
-
/**
|
1813
|
-
* @typedef {Object} ChunkGroupInfo
|
1814
|
-
* @property {Set<Module>} minAvailableModules current minimal set of modules available at this point
|
1815
|
-
* @property {Set<Module>[]} availableModulesToBeMerged enqueued updates to the minimal set of available modules
|
1816
|
-
*/
|
1817
|
-
|
1818
|
-
/** @type {Map<ChunkGroup, ChunkGroupInfo>} */
|
1819
|
-
const chunkGroupInfoMap = new Map();
|
1820
|
-
|
1821
|
-
/** @type {Queue<ChunkGroup>} */
|
1822
|
-
const queue2 = new Queue(inputChunkGroups);
|
1823
|
-
|
1824
|
-
for (const chunkGroup of inputChunkGroups) {
|
1825
|
-
chunkGroupInfoMap.set(chunkGroup, {
|
1826
|
-
minAvailableModules: undefined,
|
1827
|
-
availableModulesToBeMerged: [new Set()]
|
1828
|
-
});
|
1829
|
-
}
|
1830
|
-
|
1831
|
-
/**
|
1832
|
-
* Helper function to check if all modules of a chunk are available
|
1833
|
-
*
|
1834
|
-
* @param {ChunkGroup} chunkGroup the chunkGroup to scan
|
1835
|
-
* @param {Set<Module>} availableModules the comparitor set
|
1836
|
-
* @returns {boolean} return true if all modules of a chunk are available
|
1837
|
-
*/
|
1838
|
-
const areModulesAvailable = (chunkGroup, availableModules) => {
|
1839
|
-
for (const chunk of chunkGroup.chunks) {
|
1840
|
-
for (const module of chunk.modulesIterable) {
|
1841
|
-
if (!availableModules.has(module)) return false;
|
1842
|
-
}
|
1843
|
-
}
|
1844
|
-
return true;
|
1845
|
-
};
|
1846
|
-
|
1847
|
-
// For each edge in the basic chunk graph
|
1848
|
-
/**
|
1849
|
-
* @param {TODO} dep the dependency used for filtering
|
1850
|
-
* @returns {boolean} used to filter "edges" (aka Dependencies) that were pointing
|
1851
|
-
* to modules that are already available. Also filters circular dependencies in the chunks graph
|
1852
|
-
*/
|
1853
|
-
const filterFn = dep => {
|
1854
|
-
const depChunkGroup = dep.chunkGroup;
|
1855
|
-
if (!dep.couldBeFiltered) return true;
|
1856
|
-
if (blocksWithNestedBlocks.has(dep.block)) return true;
|
1857
|
-
if (areModulesAvailable(depChunkGroup, newAvailableModules)) {
|
1858
|
-
return false; // break all modules are already available
|
1859
|
-
}
|
1860
|
-
dep.couldBeFiltered = false;
|
1861
|
-
return true;
|
1862
|
-
};
|
1863
|
-
|
1864
|
-
// Iterative traversing of the basic chunk graph
|
1865
|
-
while (queue2.length) {
|
1866
|
-
chunkGroup = queue2.dequeue();
|
1867
|
-
const info = chunkGroupInfoMap.get(chunkGroup);
|
1868
|
-
const availableModulesToBeMerged = info.availableModulesToBeMerged;
|
1869
|
-
let minAvailableModules = info.minAvailableModules;
|
1870
|
-
|
1871
|
-
// 1. Get minimal available modules
|
1872
|
-
// It doesn't make sense to traverse a chunk again with more available modules.
|
1873
|
-
// This step calculates the minimal available modules and skips traversal when
|
1874
|
-
// the list didn't shrink.
|
1875
|
-
availableModulesToBeMerged.sort(bySetSize);
|
1876
|
-
let changed = false;
|
1877
|
-
for (const availableModules of availableModulesToBeMerged) {
|
1878
|
-
if (minAvailableModules === undefined) {
|
1879
|
-
minAvailableModules = new Set(availableModules);
|
1880
|
-
info.minAvailableModules = minAvailableModules;
|
1881
|
-
changed = true;
|
1882
|
-
} else {
|
1883
|
-
for (const m of minAvailableModules) {
|
1884
|
-
if (!availableModules.has(m)) {
|
1885
|
-
minAvailableModules.delete(m);
|
1886
|
-
changed = true;
|
1887
|
-
}
|
1888
|
-
}
|
1889
|
-
}
|
1890
|
-
}
|
1891
|
-
availableModulesToBeMerged.length = 0;
|
1892
|
-
if (!changed) continue;
|
1893
|
-
|
1894
|
-
// 2. Get the edges at this point of the graph
|
1895
|
-
const deps = chunkDependencies.get(chunkGroup);
|
1896
|
-
if (!deps) continue;
|
1897
|
-
if (deps.length === 0) continue;
|
1898
|
-
|
1899
|
-
// 3. Create a new Set of available modules at this points
|
1900
|
-
newAvailableModules = new Set(minAvailableModules);
|
1901
|
-
for (const chunk of chunkGroup.chunks) {
|
1902
|
-
for (const m of chunk.modulesIterable) {
|
1903
|
-
newAvailableModules.add(m);
|
1904
|
-
}
|
1905
|
-
}
|
1906
|
-
|
1907
|
-
// 4. Foreach remaining edge
|
1908
|
-
const nextChunkGroups = new Set();
|
1909
|
-
for (let i = 0; i < deps.length; i++) {
|
1910
|
-
const dep = deps[i];
|
1911
|
-
|
1912
|
-
// Filter inline, rather than creating a new array from `.filter()`
|
1913
|
-
if (!filterFn(dep)) {
|
1914
|
-
continue;
|
1915
|
-
}
|
1916
|
-
const depChunkGroup = dep.chunkGroup;
|
1917
|
-
const depBlock = dep.block;
|
1918
|
-
|
1919
|
-
// 5. Connect block with chunk
|
1920
|
-
GraphHelpers.connectDependenciesBlockAndChunkGroup(
|
1921
|
-
depBlock,
|
1922
|
-
depChunkGroup
|
1923
|
-
);
|
1924
|
-
|
1925
|
-
// 6. Connect chunk with parent
|
1926
|
-
GraphHelpers.connectChunkGroupParentAndChild(chunkGroup, depChunkGroup);
|
1927
|
-
|
1928
|
-
nextChunkGroups.add(depChunkGroup);
|
1929
|
-
}
|
1930
|
-
|
1931
|
-
// 7. Enqueue further traversal
|
1932
|
-
for (const nextChunkGroup of nextChunkGroups) {
|
1933
|
-
let nextInfo = chunkGroupInfoMap.get(nextChunkGroup);
|
1934
|
-
if (nextInfo === undefined) {
|
1935
|
-
nextInfo = {
|
1936
|
-
minAvailableModules: undefined,
|
1937
|
-
availableModulesToBeMerged: []
|
1938
|
-
};
|
1939
|
-
chunkGroupInfoMap.set(nextChunkGroup, nextInfo);
|
1940
|
-
}
|
1941
|
-
nextInfo.availableModulesToBeMerged.push(newAvailableModules);
|
1942
|
-
|
1943
|
-
// As queue deduplicates enqueued items this makes sure that a ChunkGroup
|
1944
|
-
// is not enqueued twice
|
1945
|
-
queue2.enqueue(nextChunkGroup);
|
1946
|
-
}
|
1947
|
-
}
|
1948
|
-
|
1949
|
-
// Remove all unconnected chunk groups
|
1950
|
-
for (const chunkGroup of allCreatedChunkGroups) {
|
1951
|
-
if (chunkGroup.getNumberOfParents() === 0) {
|
1952
|
-
for (const chunk of chunkGroup.chunks) {
|
1953
|
-
const idx = this.chunks.indexOf(chunk);
|
1954
|
-
if (idx >= 0) this.chunks.splice(idx, 1);
|
1955
|
-
chunk.remove("unconnected");
|
1956
|
-
}
|
1957
|
-
chunkGroup.remove("unconnected");
|
1958
|
-
}
|
1959
|
-
}
|
1960
|
-
}
|
1961
|
-
|
1962
1578
|
/**
|
1963
1579
|
*
|
1964
1580
|
* @param {Module} module module relationship for removal
|
@@ -2294,7 +1910,7 @@ class Compilation extends Tapable {
|
|
2294
1910
|
const module = modules[i];
|
2295
1911
|
const moduleHash = createHash(hashFunction);
|
2296
1912
|
module.updateHash(moduleHash);
|
2297
|
-
module.hash = moduleHash.digest(hashDigest);
|
1913
|
+
module.hash = /** @type {string} */ (moduleHash.digest(hashDigest));
|
2298
1914
|
module.renderedHash = module.hash.substr(0, hashDigestLength);
|
2299
1915
|
}
|
2300
1916
|
// clone needed as sort below is inplace mutation
|
@@ -2329,7 +1945,7 @@ class Compilation extends Tapable {
|
|
2329
1945
|
this.dependencyTemplates
|
2330
1946
|
);
|
2331
1947
|
this.hooks.chunkHash.call(chunk, chunkHash);
|
2332
|
-
chunk.hash = chunkHash.digest(hashDigest);
|
1948
|
+
chunk.hash = /** @type {string} */ (chunkHash.digest(hashDigest));
|
2333
1949
|
hash.update(chunk.hash);
|
2334
1950
|
chunk.renderedHash = chunk.hash.substr(0, hashDigestLength);
|
2335
1951
|
this.hooks.contentHash.call(chunk);
|
@@ -2337,7 +1953,7 @@ class Compilation extends Tapable {
|
|
2337
1953
|
this.errors.push(new ChunkRenderError(chunk, "", err));
|
2338
1954
|
}
|
2339
1955
|
}
|
2340
|
-
this.fullHash = hash.digest(hashDigest);
|
1956
|
+
this.fullHash = /** @type {string} */ (hash.digest(hashDigest));
|
2341
1957
|
this.hash = this.fullHash.substr(0, hashDigestLength);
|
2342
1958
|
}
|
2343
1959
|
|
@@ -2353,7 +1969,7 @@ class Compilation extends Tapable {
|
|
2353
1969
|
const hash = createHash(hashFunction);
|
2354
1970
|
hash.update(this.fullHash);
|
2355
1971
|
hash.update(update);
|
2356
|
-
this.fullHash = hash.digest(hashDigest);
|
1972
|
+
this.fullHash = /** @type {string} */ (hash.digest(hashDigest));
|
2357
1973
|
this.hash = this.fullHash.substr(0, hashDigestLength);
|
2358
1974
|
}
|
2359
1975
|
|
package/lib/Compiler.js
CHANGED
@@ -27,6 +27,7 @@ const ResolverFactory = require("./ResolverFactory");
|
|
27
27
|
const RequestShortener = require("./RequestShortener");
|
28
28
|
const { makePathsRelative } = require("./util/identifier");
|
29
29
|
const ConcurrentCompilationError = require("./ConcurrentCompilationError");
|
30
|
+
const { Logger } = require("./logging/Logger");
|
30
31
|
|
31
32
|
/** @typedef {import("../declarations/WebpackOptions").Entry} Entry */
|
32
33
|
/** @typedef {import("../declarations/WebpackOptions").WebpackOptions} WebpackOptions */
|
@@ -84,6 +85,9 @@ class Compiler extends Tapable {
|
|
84
85
|
/** @type {SyncHook} */
|
85
86
|
watchClose: new SyncHook([]),
|
86
87
|
|
88
|
+
/** @type {SyncBailHook<string, string, any[]>} */
|
89
|
+
infrastructurelog: new SyncBailHook(["origin", "type", "args"]),
|
90
|
+
|
87
91
|
// TODO the following hooks are weirdly located here
|
88
92
|
// TODO move them for webpack 5
|
89
93
|
/** @type {SyncHook} */
|
@@ -137,6 +141,8 @@ class Compiler extends Tapable {
|
|
137
141
|
/** @type {ResolverFactory} */
|
138
142
|
this.resolverFactory = new ResolverFactory();
|
139
143
|
|
144
|
+
this.infrastructureLogger = undefined;
|
145
|
+
|
140
146
|
// TODO remove in webpack 5
|
141
147
|
this.resolvers = {
|
142
148
|
normal: {
|
@@ -196,6 +202,33 @@ class Compiler extends Tapable {
|
|
196
202
|
this._assetEmittingWrittenFiles = new Map();
|
197
203
|
}
|
198
204
|
|
205
|
+
/**
|
206
|
+
* @param {string | (function(): string)} name name of the logger, or function called once to get the logger name
|
207
|
+
* @returns {Logger} a logger with that name
|
208
|
+
*/
|
209
|
+
getInfrastructureLogger(name) {
|
210
|
+
if (!name) {
|
211
|
+
throw new TypeError(
|
212
|
+
"Compiler.getInfrastructureLogger(name) called without a name"
|
213
|
+
);
|
214
|
+
}
|
215
|
+
return new Logger((type, args) => {
|
216
|
+
if (typeof name === "function") {
|
217
|
+
name = name();
|
218
|
+
if (!name) {
|
219
|
+
throw new TypeError(
|
220
|
+
"Compiler.getInfrastructureLogger(name) called with a function not returning a name"
|
221
|
+
);
|
222
|
+
}
|
223
|
+
}
|
224
|
+
if (this.hooks.infrastructurelog.call(name, type, args) === undefined) {
|
225
|
+
if (this.infrastructureLogger !== undefined) {
|
226
|
+
this.infrastructureLogger(name, type, args);
|
227
|
+
}
|
228
|
+
}
|
229
|
+
});
|
230
|
+
}
|
231
|
+
|
199
232
|
watch(watchOptions, handler) {
|
200
233
|
if (this.running) return handler(new ConcurrentCompilationError());
|
201
234
|
|
@@ -45,7 +45,9 @@ class HashedModuleIdsPlugin {
|
|
45
45
|
});
|
46
46
|
const hash = createHash(options.hashFunction);
|
47
47
|
hash.update(id);
|
48
|
-
const hashId = hash.digest(
|
48
|
+
const hashId = /** @type {string} */ (hash.digest(
|
49
|
+
options.hashDigest
|
50
|
+
));
|
49
51
|
let len = options.hashDigestLength;
|
50
52
|
while (usedIds.has(hashId.substr(0, len))) len++;
|
51
53
|
module.id = hashId.substr(0, len);
|