diff --git a/lib/Dependency.js b/lib/Dependency.js index 1b2eb272d..23ef5a143 100644 --- a/lib/Dependency.js +++ b/lib/Dependency.js @@ -85,9 +85,11 @@ const memoize = require("./util/memoize"); const TRANSITIVE = Symbol("transitive"); -const getIgnoredModule = memoize( - () => new RawModule("/* (ignored) */", "ignored", "(ignored)") -); +const getIgnoredModule = memoize(() => { + const module = new RawModule("/* (ignored) */", "ignored", "(ignored)"); + module.factoryMeta = { sideEffectFree: true }; + return module; +}); class Dependency { constructor() { diff --git a/lib/IgnorePlugin.js b/lib/IgnorePlugin.js index 255d5e23c..004aa8d8c 100644 --- a/lib/IgnorePlugin.js +++ b/lib/IgnorePlugin.js @@ -80,11 +80,14 @@ class IgnorePlugin { resolveData.dependencies.length > 0 && resolveData.dependencies[0] instanceof EntryDependency ) { - resolveData.ignoredModule = new RawModule( + const module = new RawModule( "", "ignored-entry-module", "(ignored-entry-module)" ); + module.factoryMeta = { sideEffectFree: true }; + + resolveData.ignoredModule = module; } return result; diff --git a/lib/RawModule.js b/lib/RawModule.js index 6167915d7..a04222520 100644 --- a/lib/RawModule.js +++ b/lib/RawModule.js @@ -24,6 +24,8 @@ const makeSerializable = require("./util/makeSerializable"); /** @typedef {import("./Module").NeedBuildCallback} NeedBuildCallback */ /** @typedef {import("./Module").NeedBuildContext} NeedBuildContext */ /** @typedef {import("./Module").ReadOnlyRuntimeRequirements} ReadOnlyRuntimeRequirements */ +/** @typedef {import("./ModuleGraph")} ModuleGraph */ +/** @typedef {import("./ModuleGraphConnection").ConnectionState} ConnectionState */ /** @typedef {import("./RequestShortener")} RequestShortener */ /** @typedef {import("./ResolverFactory").ResolverWithOptions} ResolverWithOptions */ /** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */ @@ -105,6 +107,18 @@ class RawModule extends Module { callback(); } + /** + * @param {ModuleGraph} moduleGraph the module graph + * @returns {ConnectionState} how this module should be connected to referencing modules when consumed for side-effects only + */ + getSideEffectsConnectionState(moduleGraph) { + if (this.factoryMeta !== undefined) { + if (this.factoryMeta.sideEffectFree) return false; + if (this.factoryMeta.sideEffectFree === false) return true; + } + return true; + } + /** * @param {CodeGenerationContext} context context for code generation * @returns {CodeGenerationResult} result diff --git a/lib/dependencies/ModuleDependency.js b/lib/dependencies/ModuleDependency.js index 6a5629237..26b3cf22a 100644 --- a/lib/dependencies/ModuleDependency.js +++ b/lib/dependencies/ModuleDependency.js @@ -61,11 +61,13 @@ class ModuleDependency extends Dependency { * @returns {Module} ignored module */ createIgnoredModule(context) { - return new RawModule( + const module = new RawModule( "/* (ignored) */", `ignored|${context}|${this.request}`, `${this.request} (ignored)` ); + module.factoryMeta = { sideEffectFree: true }; + return module; } /** diff --git a/test/configCases/ignore/side-effects/ignored-module.js b/test/configCases/ignore/side-effects/ignored-module.js new file mode 100644 index 000000000..4e015a52c --- /dev/null +++ b/test/configCases/ignore/side-effects/ignored-module.js @@ -0,0 +1 @@ +module.exports = "ignored"; diff --git a/test/configCases/ignore/side-effects/locales/a.js b/test/configCases/ignore/side-effects/locales/a.js new file mode 100644 index 000000000..e94fef185 --- /dev/null +++ b/test/configCases/ignore/side-effects/locales/a.js @@ -0,0 +1 @@ +export default "a"; diff --git a/test/configCases/ignore/side-effects/locales/b.js b/test/configCases/ignore/side-effects/locales/b.js new file mode 100644 index 000000000..eff703ff4 --- /dev/null +++ b/test/configCases/ignore/side-effects/locales/b.js @@ -0,0 +1 @@ +export default "b"; diff --git a/test/configCases/ignore/side-effects/test.js b/test/configCases/ignore/side-effects/test.js new file mode 100644 index 000000000..7975f3e14 --- /dev/null +++ b/test/configCases/ignore/side-effects/test.js @@ -0,0 +1,15 @@ +"use strict"; + +import "ignored-module"; +import "./ignored-module"; + +it("should remove all ignored modules", async function() { + // Current module + module with runtime code to load context modules + expect(Object.keys(__webpack_modules__)).toHaveLength(2); + + const x = "a"; + const locale = (await import("./locales/" + x)).default; + + expect(locale).toBe("a"); + expect(Object.keys(__webpack_modules__)).toHaveLength(3); +}); diff --git a/test/configCases/ignore/side-effects/webpack.config.js b/test/configCases/ignore/side-effects/webpack.config.js new file mode 100644 index 000000000..2e81f187a --- /dev/null +++ b/test/configCases/ignore/side-effects/webpack.config.js @@ -0,0 +1,18 @@ +"use strict"; + +const webpack = require("../../../../"); + +/** @type {import("../../../../").Configuration} */ +module.exports = { + entry: "./test.js", + resolve: { + alias: { + "ignored-module": false, + "./ignored-module": false + } + }, + plugins: [new webpack.IgnorePlugin({ resourceRegExp: /(b\.js|b)$/ })], + optimization: { + sideEffects: true + } +};