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/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