Skip to content

Commit 34df7ee

Browse files
authored
fix: tree-shaking unused RawModule (#19671)
1 parent 24b1ec7 commit 34df7ee

9 files changed

Lines changed: 62 additions & 5 deletions

File tree

lib/Dependency.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,11 @@ const memoize = require("./util/memoize");
8585

8686
const TRANSITIVE = Symbol("transitive");
8787

88-
const getIgnoredModule = memoize(
89-
() => new RawModule("/* (ignored) */", "ignored", "(ignored)")
90-
);
88+
const getIgnoredModule = memoize(() => {
89+
const module = new RawModule("/* (ignored) */", "ignored", "(ignored)");
90+
module.factoryMeta = { sideEffectFree: true };
91+
return module;
92+
});
9193

9294
class Dependency {
9395
constructor() {

lib/IgnorePlugin.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,14 @@ class IgnorePlugin {
8080
resolveData.dependencies.length > 0 &&
8181
resolveData.dependencies[0] instanceof EntryDependency
8282
) {
83-
resolveData.ignoredModule = new RawModule(
83+
const module = new RawModule(
8484
"",
8585
"ignored-entry-module",
8686
"(ignored-entry-module)"
8787
);
88+
module.factoryMeta = { sideEffectFree: true };
89+
90+
resolveData.ignoredModule = module;
8891
}
8992

9093
return result;

lib/RawModule.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ const makeSerializable = require("./util/makeSerializable");
2424
/** @typedef {import("./Module").NeedBuildCallback} NeedBuildCallback */
2525
/** @typedef {import("./Module").NeedBuildContext} NeedBuildContext */
2626
/** @typedef {import("./Module").ReadOnlyRuntimeRequirements} ReadOnlyRuntimeRequirements */
27+
/** @typedef {import("./ModuleGraph")} ModuleGraph */
28+
/** @typedef {import("./ModuleGraphConnection").ConnectionState} ConnectionState */
2729
/** @typedef {import("./RequestShortener")} RequestShortener */
2830
/** @typedef {import("./ResolverFactory").ResolverWithOptions} ResolverWithOptions */
2931
/** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */
@@ -105,6 +107,18 @@ class RawModule extends Module {
105107
callback();
106108
}
107109

110+
/**
111+
* @param {ModuleGraph} moduleGraph the module graph
112+
* @returns {ConnectionState} how this module should be connected to referencing modules when consumed for side-effects only
113+
*/
114+
getSideEffectsConnectionState(moduleGraph) {
115+
if (this.factoryMeta !== undefined) {
116+
if (this.factoryMeta.sideEffectFree) return false;
117+
if (this.factoryMeta.sideEffectFree === false) return true;
118+
}
119+
return true;
120+
}
121+
108122
/**
109123
* @param {CodeGenerationContext} context context for code generation
110124
* @returns {CodeGenerationResult} result

lib/dependencies/ModuleDependency.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,13 @@ class ModuleDependency extends Dependency {
6161
* @returns {Module} ignored module
6262
*/
6363
createIgnoredModule(context) {
64-
return new RawModule(
64+
const module = new RawModule(
6565
"/* (ignored) */",
6666
`ignored|${context}|${this.request}`,
6767
`${this.request} (ignored)`
6868
);
69+
module.factoryMeta = { sideEffectFree: true };
70+
return module;
6971
}
7072

7173
/**
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = "ignored";
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default "a";
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default "b";
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
"use strict";
2+
3+
import "ignored-module";
4+
import "./ignored-module";
5+
6+
it("should remove all ignored modules", async function() {
7+
// Current module + module with runtime code to load context modules
8+
expect(Object.keys(__webpack_modules__)).toHaveLength(2);
9+
10+
const x = "a";
11+
const locale = (await import("./locales/" + x)).default;
12+
13+
expect(locale).toBe("a");
14+
expect(Object.keys(__webpack_modules__)).toHaveLength(3);
15+
});
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
"use strict";
2+
3+
const webpack = require("../../../../");
4+
5+
/** @type {import("../../../../").Configuration} */
6+
module.exports = {
7+
entry: "./test.js",
8+
resolve: {
9+
alias: {
10+
"ignored-module": false,
11+
"./ignored-module": false
12+
}
13+
},
14+
plugins: [new webpack.IgnorePlugin({ resourceRegExp: /(b\.js|b)$/ })],
15+
optimization: {
16+
sideEffects: true
17+
}
18+
};

0 commit comments

Comments
 (0)