|
8 | 8 | /** @typedef {import("./index.js").IncomingMessage} IncomingMessage */ |
9 | 9 | /** @typedef {import("./index.js").ServerResponse} ServerResponse */ |
10 | 10 |
|
11 | | -/** @typedef {NonNullable<import("webpack").Configuration["stats"]>} StatsOptions */ |
| 11 | +// The object form only (no presets/booleans) — it is merged over the |
| 12 | +// middleware's own base options, which string or boolean forms cannot be. |
| 13 | +/** @typedef {import("webpack").StatsOptions} StatsOptions */ |
12 | 14 |
|
13 | 15 | /** |
14 | 16 | * @typedef {object} HotOptions |
@@ -219,7 +221,7 @@ function toBundles(statsResult, statsOptions) { |
219 | 221 | timings: true, |
220 | 222 | errors: true, |
221 | 223 | warnings: true, |
222 | | - ...(statsOptions && typeof statsOptions === "object" ? statsOptions : {}), |
| 224 | + ...statsOptions, |
223 | 225 | }; |
224 | 226 |
|
225 | 227 | // Multi-compiler stats have stats for each child compiler. |
@@ -257,18 +259,29 @@ function bundlePayload(stats, action) { |
257 | 259 | * @param {EventStream} eventStream event stream |
258 | 260 | */ |
259 | 261 | function publishBundles(bundles, previousBundles, eventStream) { |
| 262 | + /** @type {Map<string, number>} */ |
| 263 | + const occurrences = new Map(); |
| 264 | + |
260 | 265 | for (const [index, stats] of bundles.entries()) { |
261 | 266 | const name = stats.name || ""; |
262 | 267 |
|
263 | 268 | // Paired by name so a changing set of compilations (children appearing, |
264 | | - // config reloads) cannot compare a bundle against a sibling's hash; |
265 | | - // unnamed bundles fall back to their position. |
| 269 | + // config reloads) cannot compare a bundle against a sibling's hash. |
| 270 | + // Webpack does not forbid duplicate names, so same-named bundles pair by |
| 271 | + // occurrence; unnamed bundles fall back to their position. |
266 | 272 | let previous = null; |
267 | 273 |
|
268 | 274 | if (previousBundles !== null) { |
269 | | - previous = name |
270 | | - ? previousBundles.find((bundle) => (bundle.name || "") === name) || null |
271 | | - : previousBundles[index] || null; |
| 275 | + if (name) { |
| 276 | + const occurrence = occurrences.get(name) || 0; |
| 277 | + occurrences.set(name, occurrence + 1); |
| 278 | + previous = |
| 279 | + previousBundles.filter((bundle) => (bundle.name || "") === name)[ |
| 280 | + occurrence |
| 281 | + ] || null; |
| 282 | + } else { |
| 283 | + previous = previousBundles[index] || null; |
| 284 | + } |
272 | 285 | } |
273 | 286 |
|
274 | 287 | const changed = |
@@ -296,7 +309,7 @@ function publishBundles(bundles, previousBundles, eventStream) { |
296 | 309 | function createHot(compiler, userOptions) { |
297 | 310 | const options = userOptions === true ? {} : userOptions; |
298 | 311 | const path = options.path || HOT_DEFAULT_PATH; |
299 | | - const heartbeat = options.heartbeat || HOT_DEFAULT_HEARTBEAT; |
| 312 | + const heartbeat = options.heartbeat ?? HOT_DEFAULT_HEARTBEAT; |
300 | 313 | const { statsOptions } = options; |
301 | 314 | const logger = compiler.getInfrastructureLogger("webpack-dev-middleware"); |
302 | 315 |
|
|
0 commit comments