diff --git a/.cspell.json b/.cspell.json
index 75ccb46d8d..817c0ee483 100644
--- a/.cspell.json
+++ b/.cspell.json
@@ -2,6 +2,7 @@
"version": "0.2",
"language": "en,en-gb",
"words": [
+ "apos",
"camelcase",
"tapable",
"sockjs",
diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml
index bac3c2e10b..f1287eb682 100644
--- a/.github/workflows/nodejs.yml
+++ b/.github/workflows/nodejs.yml
@@ -69,7 +69,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
- node-version: [18.x, 20.x, 22.x]
+ node-version: [18.x, 20.x, 22.x, 23.x]
shard: ["1/4", "2/4", "3/4", "4/4"]
webpack-version: [latest]
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bf63204a15..420e87495c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,18 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
+## [5.2.0](https://github.com/webpack/webpack-dev-server/compare/v5.1.0...v5.2.0) (2024-12-11)
+
+
+### Features
+
+* added `getClientEntry` and `getClientHotEntry` methods to get clients entries ([dc642a8](https://github.com/webpack/webpack-dev-server/commit/dc642a832d45c23c5c7a08fbf29995e0db7e0d95))
+
+
+### Bug Fixes
+
+* speed up initial client bundling ([145b5d0](https://github.com/webpack/webpack-dev-server/commit/145b5d01610a16468fc32719a20366682b0e8572))
+
## [5.1.0](https://github.com/webpack/webpack-dev-server/compare/v5.0.4...v5.1.0) (2024-09-03)
diff --git a/client-src/index.js b/client-src/index.js
index d6614a7a67..522ae993db 100644
--- a/client-src/index.js
+++ b/client-src/index.js
@@ -1,14 +1,11 @@
/* global __resourceQuery, __webpack_hash__ */
///
import webpackHotLog from "webpack/hot/log.js";
-import stripAnsi from "./utils/stripAnsi.js";
-import parseURL from "./utils/parseURL.js";
+import hotEmitter from "webpack/hot/emitter.js";
import socket from "./socket.js";
import { formatProblem, createOverlay } from "./overlay.js";
-import { log, logEnabledFeatures, setLogLevel } from "./utils/log.js";
+import { log, setLogLevel } from "./utils/log.js";
import sendMessage from "./utils/sendMessage.js";
-import reloadApp from "./utils/reloadApp.js";
-import createSocketURL from "./utils/createSocketURL.js";
import { isProgressSupported, defineProgressElement } from "./progress.js";
/**
@@ -48,13 +45,11 @@ const decodeOverlayOptions = (overlayOptions) => {
);
// eslint-disable-next-line no-new-func
- const overlayFilterFunction = new Function(
+ overlayOptions[property] = new Function(
"message",
`var callback = ${overlayFilterFunctionString}
return callback(message)`,
);
-
- overlayOptions[property] = overlayFilterFunction;
}
});
}
@@ -69,13 +64,75 @@ const status = {
currentHash: __webpack_hash__,
};
-/** @type {Options} */
-const options = {
- hot: false,
- liveReload: false,
- progress: false,
- overlay: false,
+/**
+ * @returns {string}
+ */
+const getCurrentScriptSource = () => {
+ // `document.currentScript` is the most accurate way to find the current script,
+ // but is not supported in all browsers.
+ if (document.currentScript) {
+ return document.currentScript.getAttribute("src");
+ }
+
+ // Fallback to getting all scripts running in the document.
+ const scriptElements = document.scripts || [];
+ const scriptElementsWithSrc = Array.prototype.filter.call(
+ scriptElements,
+ (element) => element.getAttribute("src"),
+ );
+
+ if (scriptElementsWithSrc.length > 0) {
+ const currentScript =
+ scriptElementsWithSrc[scriptElementsWithSrc.length - 1];
+
+ return currentScript.getAttribute("src");
+ }
+
+ // Fail as there was no script to use.
+ throw new Error("[webpack-dev-server] Failed to get current script source.");
};
+
+/**
+ * @param {string} resourceQuery
+ * @returns {{ [key: string]: string | boolean }}
+ */
+const parseURL = (resourceQuery) => {
+ /** @type {{ [key: string]: string }} */
+ let result = {};
+
+ if (typeof resourceQuery === "string" && resourceQuery !== "") {
+ const searchParams = resourceQuery.slice(1).split("&");
+
+ for (let i = 0; i < searchParams.length; i++) {
+ const pair = searchParams[i].split("=");
+
+ result[pair[0]] = decodeURIComponent(pair[1]);
+ }
+ } else {
+ // Else, get the url from the