Skip to content

Commit 1818881

Browse files
committed
fix: hash initial chunks before runtime chunks
1 parent 7bde8ab commit 1818881

2 files changed

Lines changed: 162 additions & 1 deletion

File tree

lib/Compilation.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4693,8 +4693,8 @@ This prevents using hashes of each other and should be avoided.`);
46934693
this.logger.timeAggregate("hashing: hash chunks");
46944694
};
46954695
for (const chunk of asyncChunks) processChunk(chunk);
4696-
for (const chunk of runtimeChunks) processChunk(chunk);
46974696
for (const chunk of initialChunks) processChunk(chunk);
4697+
for (const chunk of runtimeChunks) processChunk(chunk);
46984698
if (errors.length > 0) {
46994699
errors.sort(
47004700
compareSelect((err) => err.module, compareModulesByIdentifier)

test/RealContentHashPlugin.test.js

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
"use strict";
2+
3+
require("./helpers/warmup-webpack");
4+
5+
const path = require("path");
6+
const fs = require("graceful-fs");
7+
const { Volume, createFsFromVolume } = require("memfs");
8+
const rimraf = require("rimraf");
9+
10+
const webpack = require("..");
11+
12+
describe("RealContentHashPlugin", () => {
13+
const watchIt = process.env.NO_WATCH_TESTS ? it.skip : it;
14+
15+
const tempFixturePath = path.join(
16+
__dirname,
17+
"fixtures",
18+
"temp-real-content-hash-watch-fixture"
19+
);
20+
21+
beforeEach(cleanup);
22+
23+
afterEach(cleanup);
24+
25+
/**
26+
* @returns {void} Removes the temporary fixture directory.
27+
*/
28+
function cleanup() {
29+
rimraf.sync(tempFixturePath);
30+
}
31+
32+
/**
33+
* @returns {{ asyncEntryPath: string, syncEntryPath: string, largeSharedPath: string }} Paths to the generated fixture files.
34+
*/
35+
function createFixture() {
36+
cleanup();
37+
fs.mkdirSync(tempFixturePath, { recursive: true });
38+
39+
const asyncEntryPath = path.join(tempFixturePath, "async-entry.js");
40+
const syncEntryPath = path.join(tempFixturePath, "sync-entry.js");
41+
const largeSharedPath = path.join(tempFixturePath, "large-shared.js");
42+
const largeText = "x".repeat(25000);
43+
44+
fs.writeFileSync(asyncEntryPath, "import('./sync-entry.js');\n", "utf8");
45+
fs.writeFileSync(
46+
syncEntryPath,
47+
[
48+
"import './large-shared.js';",
49+
"export const syncValue = '__SYNC__';",
50+
"console.log(syncValue);",
51+
""
52+
].join("\n"),
53+
"utf8"
54+
);
55+
fs.writeFileSync(
56+
largeSharedPath,
57+
[
58+
`const bigTextBlob = "${largeText}";`,
59+
"export const sharedValue = '__SHARED__';",
60+
"console.log(sharedValue, bigTextBlob.length);",
61+
""
62+
].join("\n"),
63+
"utf8"
64+
);
65+
66+
return {
67+
asyncEntryPath,
68+
syncEntryPath,
69+
largeSharedPath
70+
};
71+
}
72+
73+
watchIt(
74+
"should not cache stale chunk filename hashes during watch rebuilds",
75+
(done) => {
76+
const { largeSharedPath } = createFixture();
77+
const compiler = webpack({
78+
mode: "production",
79+
context: tempFixturePath,
80+
cache: {
81+
type: "memory"
82+
},
83+
entry: {
84+
async: "./async-entry.js",
85+
sync: "./sync-entry.js",
86+
light: "./sync-entry.js"
87+
},
88+
output: {
89+
path: "/dist",
90+
filename: "[contenthash].js"
91+
},
92+
optimization: {
93+
runtimeChunk: "single",
94+
splitChunks: {
95+
chunks: "all",
96+
name: "js"
97+
}
98+
}
99+
});
100+
compiler.outputFileSystem = createFsFromVolume(new Volume());
101+
102+
let watcher;
103+
let buildCount = 0;
104+
let doneCalled = false;
105+
106+
/**
107+
* @param {Error=} error error
108+
* @returns {void}
109+
*/
110+
function finish(error) {
111+
if (doneCalled) return;
112+
doneCalled = true;
113+
if (!watcher) {
114+
done(error);
115+
return;
116+
}
117+
watcher.close((closeError) => {
118+
done(error || closeError || undefined);
119+
});
120+
}
121+
122+
watcher = compiler.watch({ aggregateTimeout: 50 }, (error, stats) => {
123+
if (error) {
124+
finish(error);
125+
return;
126+
}
127+
128+
try {
129+
expect(stats).toBeTruthy();
130+
buildCount += 1;
131+
132+
if (stats.hasErrors()) {
133+
finish(
134+
new Error(
135+
stats.toString({
136+
all: false,
137+
errors: true,
138+
errorDetails: true
139+
})
140+
)
141+
);
142+
return;
143+
}
144+
145+
if (buildCount === 1) {
146+
const updatedSource = fs
147+
.readFileSync(largeSharedPath, "utf8")
148+
.replace("__SHARED__", "__SHARED__CHANGED");
149+
fs.writeFileSync(largeSharedPath, updatedSource, "utf8");
150+
return;
151+
}
152+
153+
expect(buildCount).toBe(2);
154+
finish();
155+
} catch (err) {
156+
finish(err);
157+
}
158+
});
159+
}
160+
);
161+
});

0 commit comments

Comments
 (0)