Skip to content

Commit bf00b73

Browse files
authored
fix: reuse async entrypoint for same Worker URL within a module (#20345)
1 parent 22e1787 commit bf00b73

File tree

6 files changed

+62
-13
lines changed

6 files changed

+62
-13
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"webpack": patch
3+
---
4+
5+
Reuse the same async entrypoint for the same Worker URL within a module to avoid circular dependency warnings when multiple Workers reference the same resource.

lib/AsyncDependenciesBlock.js

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const makeSerializable = require("./util/makeSerializable");
1616
/** @typedef {import("./serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
1717
/** @typedef {import("./util/Hash")} Hash */
1818

19-
/** @typedef {(ChunkGroupOptions & { entryOptions?: EntryOptions }) | string} GroupOptions */
19+
/** @typedef {(ChunkGroupOptions & { entryOptions?: EntryOptions } & { key?: string | boolean }) | string} GroupOptions */
2020

2121
class AsyncDependenciesBlock extends DependenciesBlock {
2222
/**
@@ -56,6 +56,33 @@ class AsyncDependenciesBlock extends DependenciesBlock {
5656
}
5757
}
5858

59+
/**
60+
* @returns {boolean} Whether to deduplicate to avoid circular references
61+
*/
62+
get circular() {
63+
if (this.groupOptions.key) {
64+
return false;
65+
}
66+
return true;
67+
}
68+
69+
/**
70+
* @returns {string} the identifier of the block
71+
*/
72+
identifier() {
73+
let identifier = `entry-${Boolean(this.groupOptions.entryOptions)}`;
74+
if (this.groupOptions.name) {
75+
identifier += `|${this.groupOptions.name}`;
76+
}
77+
if (this.request) {
78+
identifier += `|${this.request}`;
79+
}
80+
if (typeof this.groupOptions.key === "string") {
81+
identifier += `|${this.groupOptions.key}`;
82+
}
83+
return identifier;
84+
}
85+
5986
/**
6087
* @param {Hash} hash the hash used to track dependencies
6188
* @param {UpdateHashContext} context context

lib/buildChunkGraph.js

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ const { getEntryRuntime, mergeRuntime } = require("./util/runtime");
5050
* @property {number} postOrderIndex next post order index
5151
* @property {boolean} chunkLoading has a chunk loading mechanism
5252
* @property {boolean} asyncChunks create async chunks
53+
* @property {string} blockId is the block key
54+
* @property {boolean} circular Whether to deduplicate to avoid circular references
5355
*/
5456

5557
/**
@@ -361,6 +363,9 @@ const visitModules = (
361363
/** @type {NamedChunkGroup} */
362364
const namedAsyncEntrypoints = new Map();
363365

366+
/** @type {Map<string, ChunkGroupInfo>} */
367+
const idAsyncEntrypoints = new Map();
368+
364369
/** @type {Set<ChunkGroupInfo>} */
365370
const outdatedOrderIndexChunkGroups = new Set();
366371

@@ -390,6 +395,8 @@ const visitModules = (
390395
);
391396
/** @type {ChunkGroupInfo} */
392397
const chunkGroupInfo = {
398+
blockId: "",
399+
circular: false,
393400
initialized: false,
394401
chunkGroup,
395402
runtime,
@@ -502,7 +509,9 @@ const visitModules = (
502509
if (cgi === undefined) {
503510
const chunkName = (b.groupOptions && b.groupOptions.name) || b.chunkName;
504511
if (entryOptions) {
505-
cgi = namedAsyncEntrypoints.get(/** @type {string} */ (chunkName));
512+
cgi =
513+
namedAsyncEntrypoints.get(/** @type {string} */ (chunkName)) ||
514+
idAsyncEntrypoints.get(/** @type {string} */ (b.identifier()));
506515
if (!cgi) {
507516
entrypoint = compilation.addAsyncEntrypoint(
508517
entryOptions,
@@ -513,6 +522,8 @@ const visitModules = (
513522
maskByChunk.set(entrypoint.chunks[0], ZERO_BIGINT);
514523
entrypoint.index = nextChunkGroupIndex++;
515524
cgi = {
525+
blockId: b.identifier(),
526+
circular: b.circular,
516527
chunkGroup: entrypoint,
517528
initialized: false,
518529
runtime:
@@ -550,6 +561,12 @@ const visitModules = (
550561
(cgi)
551562
);
552563
}
564+
if (b.circular) {
565+
idAsyncEntrypoints.set(
566+
b.identifier(),
567+
/** @type {ChunkGroupInfo} */ (cgi)
568+
);
569+
}
553570
} else {
554571
entrypoint = /** @type {Entrypoint} */ (cgi.chunkGroup);
555572
// TODO merge entryOptions
@@ -592,6 +609,8 @@ const visitModules = (
592609
maskByChunk.set(c.chunks[0], ZERO_BIGINT);
593610
c.index = nextChunkGroupIndex++;
594611
cgi = {
612+
blockId: b.identifier(),
613+
circular: b.circular,
595614
initialized: false,
596615
chunkGroup: c,
597616
runtime: chunkGroupInfo.runtime,
@@ -668,7 +687,10 @@ const visitModules = (
668687
chunkGroupInfo: /** @type {ChunkGroupInfo} */ (cgi)
669688
}
670689
]);
671-
} else if (entrypoint !== undefined) {
690+
} else if (
691+
entrypoint !== undefined &&
692+
(chunkGroupInfo.circular || chunkGroupInfo.blockId !== b.identifier())
693+
) {
672694
chunkGroupInfo.chunkGroup.addAsyncEntrypoint(entrypoint);
673695
}
674696
};

lib/dependencies/WorkerPlugin.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,7 @@ class WorkerPlugin {
387387

388388
const block = new AsyncDependenciesBlock({
389389
name: entryOptions.name,
390+
key: url,
390391
entryOptions: {
391392
chunkLoading: this._chunkLoading,
392393
wasmLoading: this._wasmLoading,

test/configCases/worker/self-import/warnings.js

Lines changed: 0 additions & 8 deletions
This file was deleted.

types.d.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -461,16 +461,18 @@ declare class AsyncDependenciesBlock extends DependenciesBlock {
461461
| string
462462
| (RawChunkGroupOptions & { name?: null | string } & {
463463
entryOptions?: EntryOptions;
464-
}),
464+
} & { key?: string | boolean }),
465465
loc?: null | SyntheticDependencyLocation | RealDependencyLocation,
466466
request?: null | string
467467
);
468468
groupOptions: RawChunkGroupOptions & { name?: null | string } & {
469469
entryOptions?: EntryOptions;
470-
};
470+
} & { key?: string | boolean };
471471
loc?: null | SyntheticDependencyLocation | RealDependencyLocation;
472472
request?: null | string;
473473
chunkName?: null | string;
474+
get circular(): boolean;
475+
identifier(): string;
474476
module: any;
475477
}
476478
declare abstract class AsyncQueue<T, K, R> {

0 commit comments

Comments
 (0)