Skip to content

Commit 5ecc58d

Browse files
authored
feat: consider asset module as side-effect-free (#20352)
1 parent cce0f69 commit 5ecc58d

11 files changed

Lines changed: 112 additions & 7 deletions

File tree

.changeset/two-tips-sniff.md

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+
Consider asset modulem to be side-effect free.

lib/asset/AssetModulesPlugin.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ const memoize = require("../util/memoize");
2727
/** @typedef {import("../Module").BuildInfo} BuildInfo */
2828
/** @typedef {import("../Module").CodeGenerationResult} CodeGenerationResult */
2929
/** @typedef {import("../NormalModule")} NormalModule */
30+
/** @typedef {import("../NormalModule").NormalModuleCreateData} NormalModuleCreateData */
3031

3132
/**
3233
* @param {string} name name of definitions
@@ -80,6 +81,7 @@ const getAssetSourceGenerator = memoize(() =>
8081
require("./AssetSourceGenerator")
8182
);
8283
const getAssetBytesGenerator = memoize(() => require("./AssetBytesGenerator"));
84+
const getNormalModule = memoize(() => require("../NormalModule"));
8385

8486
const type = ASSET_MODULE_TYPE;
8587
const PLUGIN_NAME = "AssetModulesPlugin";
@@ -94,6 +96,27 @@ class AssetModulesPlugin {
9496
compiler.hooks.compilation.tap(
9597
PLUGIN_NAME,
9698
(compilation, { normalModuleFactory }) => {
99+
const NormalModule = getNormalModule();
100+
for (const type of [
101+
ASSET_MODULE_TYPE,
102+
ASSET_MODULE_TYPE_BYTES,
103+
ASSET_MODULE_TYPE_INLINE,
104+
ASSET_MODULE_TYPE_RESOURCE,
105+
ASSET_MODULE_TYPE_SOURCE
106+
]) {
107+
normalModuleFactory.hooks.createModuleClass
108+
.for(type)
109+
.tap(PLUGIN_NAME, (createData, _resolveData) => {
110+
// TODO create the module via new AssetModule with its own properties
111+
const module = new NormalModule(
112+
/** @type {NormalModuleCreateData} */
113+
(createData)
114+
);
115+
module.factoryMeta = { sideEffectFree: true };
116+
return module;
117+
});
118+
}
119+
97120
normalModuleFactory.hooks.createParser
98121
.for(ASSET_MODULE_TYPE)
99122
.tap(PLUGIN_NAME, (parserOptions) => {

test/__snapshots__/StatsTestCases.basictest.js.snap

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,8 @@ chunk {main} (runtime: main) bundle.js (main) X bytes (javascript) X bytes (runt
136136
data:text/plain;base64,szsaAAdsadasdfaf.. X bytes {main} [depth 1] [dependent] [built] [code generated]
137137
[no exports]
138138
[used exports unknown]
139-
harmony side effect evaluation data:text/plain;base64,szsaAAdsadasdfaf.. [./index.js] 1:0-81
139+
[inactive] harmony side effect evaluation data:text/plain;base64,szsaAAdsadasdfaf.. [./index.js] 1:0-82
140+
harmony import specifier data:text/plain;base64,szsaAAdsadasdfaf.. [./index.js] 4:8-13
140141
webpack/runtime/make namespace object X bytes {main} [code generated]
141142
[no exports]
142143
[used exports unknown]
@@ -147,7 +148,8 @@ chunk {main} (runtime: main) bundle.js (main) X bytes (javascript) X bytes (runt
147148
data:text/plain;base64,szsaAAdsadasdfaf.. X bytes {main} [depth 1] [built] [code generated]
148149
[no exports]
149150
[used exports unknown]
150-
harmony side effect evaluation data:text/plain;base64,szsaAAdsadasdfaf.. [./index.js] 1:0-81
151+
[inactive] harmony side effect evaluation data:text/plain;base64,szsaAAdsadasdfaf.. [./index.js] 1:0-82
152+
harmony import specifier data:text/plain;base64,szsaAAdsadasdfaf.. [./index.js] 4:8-13
151153
webpack/runtime/make namespace object X bytes {main} [code generated]
152154
[no exports]
153155
[used exports unknown]
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import asset from "./unused.png?asset";
2+
import bytes from "./unused.png?bytes";
3+
import inlined from "./unused.png?inline";
4+
import source from "./unused.png?source";
5+
import resource from "./used.png";
6+
7+
it("should not include unused assets", () => {
8+
expect(resource).toMatch(/\.png/);
9+
10+
expect(__webpack_modules__["./used.png"]).toBeDefined();
11+
expect(__webpack_modules__["./unused.png?asset"]).not.toBeDefined();
12+
expect(__webpack_modules__["./unused.png?bytes"]).not.toBeDefined();
13+
expect(__webpack_modules__["./unused.png?inline"]).not.toBeDefined();
14+
expect(__webpack_modules__["./unused.png?source"]).not.toBeDefined();
15+
});
14.6 KB
Loading
14.6 KB
Loading
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
"use strict";
2+
3+
/** @type {import("../../../../").Configuration} */
4+
module.exports = {
5+
mode: "production",
6+
module: {
7+
rules: [
8+
{
9+
oneOf: [
10+
{
11+
test: /\.png$/i,
12+
resourceQuery: /asset/,
13+
type: "asset"
14+
},
15+
{
16+
test: /\.png$/i,
17+
resourceQuery: /bytes/,
18+
type: "asset/bytes"
19+
},
20+
{
21+
test: /\.png$/i,
22+
resourceQuery: /inline/,
23+
type: "asset/inline"
24+
},
25+
{
26+
test: /\.png$/i,
27+
resourceQuery: /source/,
28+
type: "asset/source"
29+
},
30+
{ test: /\.png$/i, type: "asset/resource" }
31+
]
32+
}
33+
]
34+
},
35+
optimization: {
36+
sideEffects: true,
37+
moduleIds: "named",
38+
concatenateModules: false
39+
}
40+
};

test/fixtures/uses-asset.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1-
import SVG from './file.svg';
1+
import SVG from "./file.svg";
2+
3+
const call = () => SVG;
4+
5+
call();

test/statsCases/all-stats/index.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,7 @@
1-
import text1 from "data:text/plain;base64,szsaAAdsadasdfafasfasAADas123aasdasd=="
1+
import text1 from "data:text/plain;base64,szsaAAdsadasdfafasfasAADas123aasdasd==";
2+
3+
const call = () => {
4+
return text1;
5+
};
6+
7+
call();

test/statsCases/asset-concat/index.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,13 @@ import png from "./images/file.png";
22
import svg from "./images/file.svg";
33
import jpg from "./images/file.jpg";
44
import html from "./static/file.html";
5-
import text1 from "data:text/plain;base64,szsaAAdsadasdfafasfasAADas123aasdasd=="
6-
import text2 from "data:text/plain,asd="
7-
import text3 from "data:text/plain,XXXXXXXXXXXXXXXXX" // 17 chars
5+
import text1 from "data:text/plain;base64,szsaAAdsadasdfafasfasAADas123aasdasd==";
6+
import text2 from "data:text/plain,asd=";
7+
import text3 from "data:text/plain,XXXXXXXXXXXXXXXXX"; // 17 chars
88
import css from "./a.css";
99
import source from "./a.source";
10+
11+
const call = () =>
12+
png + svg + jpg + html + text1 + text2 + text3 + css + source;
13+
14+
call();

0 commit comments

Comments
 (0)