Move AsyncDependenciesBlock.chunkGroup into ChunkGraph

This commit is contained in:
Tobias Koppers 2018-08-22 20:17:49 +02:00
parent 3aa2280498
commit 670502fc81
17 changed files with 131 additions and 79 deletions

View File

@ -29,8 +29,6 @@ class AsyncDependenciesBlock extends DependenciesBlock {
groupOptions = { name: undefined };
}
this.groupOptions = groupOptions;
/** @type {ChunkGroup=} */
this.chunkGroup = undefined;
this.loc = loc;
this.request = request;
/** @type {DependenciesBlock} */
@ -61,33 +59,10 @@ class AsyncDependenciesBlock extends DependenciesBlock {
*/
updateHash(hash, compilation) {
hash.update(JSON.stringify(this.groupOptions));
hash.update(
(this.chunkGroup &&
this.chunkGroup.chunks
.map(chunk => {
return chunk.id !== null ? chunk.id : "";
})
.join(",")) ||
""
);
const chunkGroup = compilation.chunkGraph.getBlockChunkGroup(this);
hash.update(chunkGroup ? chunkGroup.id : "");
super.updateHash(hash, compilation);
}
/**
* @returns {void}
*/
disconnect() {
this.chunkGroup = undefined;
super.disconnect();
}
/**
* @returns {void}
*/
unseal() {
this.chunkGroup = undefined;
super.unseal();
}
}
Object.defineProperty(AsyncDependenciesBlock.prototype, "module", {

View File

@ -9,6 +9,7 @@ const util = require("util");
const SortableSet = require("./util/SortableSet");
const { compareModulesById } = require("./util/comparators");
/** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */
/** @typedef {import("./Chunk")} Chunk */
/** @typedef {import("./ChunkGroup")} ChunkGroup */
/** @typedef {import("./Module")} Module */
@ -99,6 +100,8 @@ class ChunkGraph {
this._modules = new WeakMap();
/** @private @type {WeakMap<Chunk, ChunkGraphChunk>} */
this._chunks = new WeakMap();
/** @private @type {WeakMap<AsyncDependenciesBlock, ChunkGroup>} */
this._blockChunkGroups = new WeakMap();
/** @private @type {ModuleGraph} */
this._moduleGraph = moduleGraph;
}
@ -678,6 +681,36 @@ class ChunkGraph {
return cgc.entryModules;
}
/**
* @param {AsyncDependenciesBlock} depBlock the async block
* @returns {ChunkGroup} the chunk group
*/
getBlockChunkGroup(depBlock) {
return this._blockChunkGroups.get(depBlock);
}
/**
* @param {AsyncDependenciesBlock} depBlock the async block
* @param {ChunkGroup} chunkGroup the chunk group
* @returns {void}
*/
connectBlockAndChunkGroup(depBlock, chunkGroup) {
this._blockChunkGroups.set(depBlock, chunkGroup);
chunkGroup.addBlock(depBlock);
}
/**
* @param {ChunkGroup} chunkGroup the chunk group
* @returns {void}
*/
disconnectChunkGroup(chunkGroup) {
for (const block of chunkGroup.blocksIterable) {
this._blockChunkGroups.delete(block);
}
// TODO refactor by moving blocks list into ChunkGraph
chunkGroup._blocks.clear();
}
/**
* @param {Module} module the module
* @returns {string} hash

View File

@ -381,11 +381,6 @@ class ChunkGroup {
chunkGroup._parents.delete(this);
}
// cleanup blocks
for (const block of this._blocks) {
block.chunkGroup = null;
}
// remove chunks
for (const chunk of this.chunks) {
chunk.removeGroup(this);

View File

@ -24,8 +24,7 @@ const EntryModuleNotFoundError = require("./EntryModuleNotFoundError");
const Entrypoint = require("./Entrypoint");
const {
connectChunkGroupAndChunk,
connectChunkGroupParentAndChild,
connectDependenciesBlockAndChunkGroup
connectChunkGroupParentAndChild
} = require("./GraphHelpers");
const HotUpdateChunkTemplate = require("./HotUpdateChunkTemplate");
const MainTemplate = require("./MainTemplate");
@ -1396,7 +1395,9 @@ class Compilation {
const moduleGraph = this.moduleGraph;
/** @type {Map<ChunkGroup, {block: AsyncDependenciesBlock, chunkGroup: ChunkGroup}[]>} */
/** @typedef {{block: AsyncDependenciesBlock, chunkGroup: ChunkGroup}} ChunkGroupDep */
/** @type {Map<ChunkGroup, ChunkGroupDep[]>} */
const chunkDependencies = new Map();
/** @type {Set<ChunkGroup>} */
const allCreatedChunkGroups = new Set();
@ -1726,7 +1727,7 @@ class Compilation {
// For each edge in the basic chunk graph
/**
* @param {TODO} dep the dependency used for filtering
* @param {ChunkGroupDep} dep the dependency used for filtering
* @returns {boolean} used to filter "edges" (aka Dependencies) that were pointing
* to modules that are already available. Also filters circular dependencies in the chunks graph
*/
@ -1789,7 +1790,7 @@ class Compilation {
const depBlock = dep.block;
// 6. Connect block with chunk
connectDependenciesBlockAndChunkGroup(depBlock, depChunkGroup);
chunkGraph.connectBlockAndChunkGroup(depBlock, depChunkGroup);
// 7. Connect chunk with parent
connectChunkGroupParentAndChild(chunkGroup, depChunkGroup);
@ -1814,6 +1815,7 @@ class Compilation {
if (idx >= 0) this.chunks.splice(idx, 1);
chunkGraph.disconnectChunk(chunk);
}
chunkGraph.disconnectChunkGroup(chunkGroup);
chunkGroup.remove();
}
}
@ -1883,13 +1885,14 @@ class Compilation {
const blocks = block.blocks;
for (let indexBlock = 0; indexBlock < blocks.length; indexBlock++) {
const asyncBlock = blocks[indexBlock];
const chunkGroup = this.chunkGraph.getBlockChunkGroup(asyncBlock);
// Grab all chunks from the first Block's AsyncDepBlock
const chunks = asyncBlock.chunkGroup.chunks;
const chunks = chunkGroup.chunks;
// For each chunk in chunkGroup
for (let indexChunk = 0; indexChunk < chunks.length; indexChunk++) {
const iteratedChunk = chunks[indexChunk];
asyncBlock.chunkGroup.removeChunk(iteratedChunk);
asyncBlock.chunkGroup.removeParent(iteratedChunk);
chunkGroup.removeChunk(iteratedChunk);
chunkGroup.removeParent(iteratedChunk);
// Recurse
this.removeChunkFromDependencies(block, iteratedChunk);
}

View File

@ -561,8 +561,14 @@ webpackAsyncContext.id = ${JSON.stringify(id)};
module.exports = webpackAsyncContext;`;
}
getLazyOnceSource(block, dependencies, id, { runtimeTemplate, moduleGraph }) {
getLazyOnceSource(
block,
dependencies,
id,
{ runtimeTemplate, moduleGraph, chunkGraph }
) {
const promise = runtimeTemplate.blockPromise({
chunkGraph,
block,
message: "lazy-once context"
});
@ -600,7 +606,7 @@ webpackAsyncContext.id = ${JSON.stringify(id)};
module.exports = webpackAsyncContext;`;
}
getLazySource(blocks, id, moduleGraph) {
getLazySource(blocks, id, moduleGraph, chunkGraph) {
let hasMultipleOrNoChunks = false;
const fakeMap = this.getFakeMap(
blocks.map(b => b.dependencies[0]),
@ -622,8 +628,8 @@ module.exports = webpackAsyncContext;`;
return a.userRequest < b.userRequest ? -1 : 1;
})
.reduce((map, item) => {
const chunks =
(item.block.chunkGroup && item.block.chunkGroup.chunks) || [];
const chunkGroup = chunkGraph.getBlockChunkGroup(item.block);
const chunks = (chunkGroup && chunkGroup.chunks) || [];
if (chunks.length !== 1) {
hasMultipleOrNoChunks = true;
}
@ -697,10 +703,20 @@ module.exports = webpackEmptyAsyncContext;
webpackEmptyAsyncContext.id = ${JSON.stringify(id)};`;
}
getSourceString(asyncMode, { runtimeTemplate, moduleGraph }) {
/**
* @param {string} asyncMode module mode
* @param {SourceContext} sourceContext context info
* @returns {string} the source code
*/
getSourceString(asyncMode, { runtimeTemplate, moduleGraph, chunkGraph }) {
if (asyncMode === "lazy") {
if (this.blocks && this.blocks.length > 0) {
return this.getLazySource(this.blocks, this.id, moduleGraph);
return this.getLazySource(
this.blocks,
this.id,
moduleGraph,
chunkGraph
);
}
return this.getSourceForEmptyAsyncContext(this.id);
}
@ -715,7 +731,8 @@ webpackEmptyAsyncContext.id = ${JSON.stringify(id)};`;
if (block) {
return this.getLazyOnceSource(block, block.dependencies, this.id, {
runtimeTemplate,
moduleGraph
moduleGraph,
chunkGraph
});
}
return this.getSourceForEmptyAsyncContext(this.id);
@ -748,9 +765,9 @@ webpackEmptyAsyncContext.id = ${JSON.stringify(id)};`;
* @param {SourceContext} sourceContext source context
* @returns {Source} generated source
*/
source({ runtimeTemplate, moduleGraph }) {
source(sourceContext) {
return this.getSource(
this.getSourceString(this.options.mode, { runtimeTemplate, moduleGraph })
this.getSourceString(this.options.mode, sourceContext)
);
}

View File

@ -6,6 +6,7 @@
"use strict";
/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
/** @typedef {import("./ChunkGraph")} ChunkGraph */
/** @typedef {import("./Dependency")} Dependency */
/** @typedef {import("./DependencyTemplates")} DependencyTemplates */
/** @typedef {import("./InitFragment")} InitFragment */
@ -18,6 +19,7 @@
* @property {RuntimeTemplate} runtimeTemplate the runtime template
* @property {DependencyTemplates} dependencyTemplates the dependency templates
* @property {ModuleGraph} moduleGraph the module graph
* @property {ChunkGraph} chunkGraph the chunk graph
* @property {Module} module current module
*/

View File

@ -6,6 +6,7 @@
"use strict";
/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("./ChunkGraph")} ChunkGraph */
/** @typedef {import("./DependencyTemplate")} DependencyTemplate */
/** @typedef {import("./DependencyTemplates")} DependencyTemplates */
/** @typedef {import("./ModuleGraph")} ModuleGraph */
@ -17,6 +18,7 @@
* @property {DependencyTemplates} dependencyTemplates mapping from dependencies to templates
* @property {RuntimeTemplate} runtimeTemplate the runtime template
* @property {ModuleGraph} moduleGraph the module graph
* @property {ChunkGraph} chunkGraph the chunk graph
* @property {string} type which kind of code should be generated
*/

View File

@ -33,17 +33,5 @@ const connectChunkGroupParentAndChild = (parent, child) => {
}
};
/**
* @param {AsyncDependenciesBlock} depBlock DepBlock being tied to ChunkGroup
* @param {ChunkGroup} chunkGroup ChunkGroup being tied to DepBlock
* @returns {void}
*/
const connectDependenciesBlockAndChunkGroup = (depBlock, chunkGroup) => {
if (chunkGroup.addBlock(depBlock)) {
depBlock.chunkGroup = chunkGroup;
}
};
exports.connectChunkGroupAndChunk = connectChunkGroupAndChunk;
exports.connectChunkGroupParentAndChild = connectChunkGroupParentAndChild;
exports.connectDependenciesBlockAndChunkGroup = connectDependenciesBlockAndChunkGroup;

View File

@ -135,6 +135,7 @@ class JavascriptGenerator extends Generator {
runtimeTemplate: generateContext.runtimeTemplate,
dependencyTemplates: generateContext.dependencyTemplates,
moduleGraph: generateContext.moduleGraph,
chunkGraph: generateContext.chunkGraph,
module
};

View File

@ -527,6 +527,7 @@ class NormalModule extends Module {
dependencyTemplates,
runtimeTemplate,
moduleGraph,
chunkGraph,
type
});

View File

@ -8,6 +8,7 @@
const Template = require("./Template");
/** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */
/** @typedef {import("./ChunkGraph")} ChunkGraph */
/** @typedef {import("./Module")} Module */
/** @typedef {import("./ModuleGraph")} ModuleGraph */
/** @typedef {import("./RequestShortener")} RequestShortener */
@ -259,6 +260,7 @@ module.exports = class RuntimeTemplate {
/**
* @param {Object} options options object
* @param {ChunkGraph} options.chunkGraph the chunk graph
* @param {AsyncDependenciesBlock=} options.block the current dependencies block
* @param {Module} options.module the module
* @param {string} options.request the request that should be printed as comment
@ -267,7 +269,15 @@ module.exports = class RuntimeTemplate {
* @param {boolean=} options.weak if the dependency is weak (will create a nice error message)
* @returns {string} the promise expression
*/
moduleNamespacePromise({ block, module, request, message, strict, weak }) {
moduleNamespacePromise({
chunkGraph,
block,
module,
request,
message,
strict,
weak
}) {
if (!module) {
return this.missingModulePromise({
request
@ -288,6 +298,7 @@ module.exports = class RuntimeTemplate {
);
}
const promise = this.blockPromise({
chunkGraph,
block,
message
});
@ -488,14 +499,21 @@ module.exports = class RuntimeTemplate {
}
}
blockPromise({ block, message }) {
if (!block || !block.chunkGroup || block.chunkGroup.chunks.length === 0) {
blockPromise({ block, message, chunkGraph }) {
if (!block) {
const comment = this.comment({
message
});
return `Promise.resolve(${comment.trim()})`;
}
const chunks = block.chunkGroup.chunks.filter(
const chunkGroup = chunkGraph.getBlockChunkGroup(block);
if (!chunkGroup || chunkGroup.chunks.length === 0) {
const comment = this.comment({
message
});
return `Promise.resolve(${comment.trim()})`;
}
const chunks = chunkGroup.chunks.filter(
chunk => !chunk.hasRuntime() && chunk.id !== null
);
const comment = this.comment({

View File

@ -25,10 +25,11 @@ AMDRequireDependency.Template = class AMDRequireDependencyTemplate extends NullD
* @param {DependencyTemplateContext} templateContext the context object
* @returns {void}
*/
apply(dependency, source, { runtimeTemplate }) {
apply(dependency, source, { runtimeTemplate, chunkGraph }) {
const dep = /** @type {AMDRequireDependency} */ (dependency);
const depBlock = dep.block;
const promise = runtimeTemplate.blockPromise({
chunkGraph,
block: depBlock,
message: "AMD require"
});

View File

@ -29,9 +29,14 @@ ImportDependency.Template = class ImportDependencyTemplate extends ModuleDepende
* @param {DependencyTemplateContext} templateContext the context object
* @returns {void}
*/
apply(dependency, source, { runtimeTemplate, module, moduleGraph }) {
apply(
dependency,
source,
{ runtimeTemplate, module, moduleGraph, chunkGraph }
) {
const dep = /** @type {ImportDependency} */ (dependency);
const content = runtimeTemplate.moduleNamespacePromise({
chunkGraph,
block: dep.block,
module: moduleGraph.getModule(dep),
request: dep.request,

View File

@ -29,9 +29,14 @@ ImportEagerDependency.Template = class ImportEagerDependencyTemplate extends Mod
* @param {DependencyTemplateContext} templateContext the context object
* @returns {void}
*/
apply(dependency, source, { runtimeTemplate, module, moduleGraph }) {
apply(
dependency,
source,
{ runtimeTemplate, module, moduleGraph, chunkGraph }
) {
const dep = /** @type {ImportEagerDependency} */ (dependency);
const content = runtimeTemplate.moduleNamespacePromise({
chunkGraph,
module: moduleGraph.getModule(dep),
request: dep.request,
strict: module.buildMeta.strictHarmonyModule,

View File

@ -30,9 +30,14 @@ ImportWeakDependency.Template = class ImportDependencyTemplate extends ModuleDep
* @param {DependencyTemplateContext} templateContext the context object
* @returns {void}
*/
apply(dependency, source, { runtimeTemplate, module, moduleGraph }) {
apply(
dependency,
source,
{ runtimeTemplate, module, moduleGraph, chunkGraph }
) {
const dep = /** @type {ImportWeakDependency} */ (dependency);
const content = runtimeTemplate.moduleNamespacePromise({
chunkGraph,
module: moduleGraph.getModule(dep),
request: dep.request,
strict: module.buildMeta.strictHarmonyModule,

View File

@ -29,10 +29,11 @@ RequireEnsureDependency.Template = class RequireEnsureDependencyTemplate extends
* @param {DependencyTemplateContext} templateContext the context object
* @returns {void}
*/
apply(dependency, source, { runtimeTemplate }) {
apply(dependency, source, { runtimeTemplate, chunkGraph }) {
const dep = /** @type {RequireEnsureDependency} */ (dependency);
const depBlock = dep.block;
const promise = runtimeTemplate.blockPromise({
chunkGraph,
block: depBlock,
message: "require.ensure"
});

View File

@ -57,7 +57,7 @@ Child content-change:
`;
exports[`StatsTestCases should print correct stats for aggressive-splitting-on-demand 1`] = `
"Hash: 9418f05bd974463160e9
"Hash: ac44043dd369f76c1a58
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]
9162e370d5b0e4d1fe70.js 9.7 KiB 10 [emitted] main
39c759b5ad724be84491.js 9.7 KiB 10 [emitted] main
ba9fedb7aa0c69201639.js 1.94 KiB 11 [emitted]
Entrypoint main = 9162e370d5b0e4d1fe70.js
Entrypoint main = 39c759b5ad724be84491.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} 9162e370d5b0e4d1fe70.js (main) 248 bytes >{0}< >{1}< >{2}< >{3}< >{4}< >{5}< >{6}< >{7}< >{8}< >{9}< >{11}< [entry] [rendered]
chunk {10} 39c759b5ad724be84491.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
@ -1123,7 +1123,7 @@ Compilation error while processing magic comment(-s): /* webpackPrefetch: true,
`;
exports[`StatsTestCases should print correct stats for issue-7577 1`] = `
"Hash: 85309305fa40259fb1ebc74e886ded34938c99afb793a0bac9d49c018eb7
"Hash: 85309305fa40259fb1ebc74e886ded34938c99af5a13e5bb0f1d4eda700f
Child
Hash: 85309305fa40259fb1eb
Time: Xms
@ -1147,16 +1147,16 @@ Child
[0] ./b.js 17 bytes {all~main} [built]
[1] ./node_modules/vendor.js 23 bytes {vendors~main} [built]
Child
Hash: b793a0bac9d49c018eb7
Hash: 5a13e5bb0f1d4eda700f
Time: Xms
Built at: Thu Jan 01 1970 00:00:00 GMT
Asset Size Chunks Chunk Names
c-main-395ed4acf6a1f211e7f1.js 114 bytes main [emitted] main
c-main-12e92c09639c8ffd175e.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-all~main-bf18c70b37bda892ef52.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-395ed4acf6a1f211e7f1.js (prefetch: c-0-598d23de6ad7df2ab6e4.js c-1-9039f4a1a11a97f28320.js)
Entrypoint main = c-runtime~main-54fe8e7231733bcf484a.js c-all~main-bf18c70b37bda892ef52.js c-main-12e92c09639c8ffd175e.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]"