From 5f340d6ed9af9b1e242cdd4c2128ad45b976d7d4 Mon Sep 17 00:00:00 2001
From: Rishabh Chawla <rishabh31121999@gmail.com>
Date: Thu, 16 Sep 2021 12:23:29 +0530
Subject: [PATCH 1/9] chore: add stub

---
 lib/Server.js | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/lib/Server.js b/lib/Server.js
index 5d1c6835d5..b4da766c85 100644
--- a/lib/Server.js
+++ b/lib/Server.js
@@ -36,6 +36,17 @@ class Server {
     this.webSocketProxies = [];
     this.sockets = [];
     this.compiler = compiler;
+    
+    if (this.compiler) {
+      this.apply(compiler);
+    }
+  }
+
+  apply(compiler) {
+    if (!compiler.compilers) {
+      this.start();
+    }
+
   }
 
   static get DEFAULT_STATS() {

From 8265a6114e3afe6564ebcd19d9c9092d95e037f6 Mon Sep 17 00:00:00 2001
From: Rishabh Chawla <rishabh31121999@gmail.com>
Date: Thu, 16 Sep 2021 14:07:58 +0530
Subject: [PATCH 2/9] chore: complete plugin support

---
 lib/Server.js | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/lib/Server.js b/lib/Server.js
index b4da766c85..8d0b77a028 100644
--- a/lib/Server.js
+++ b/lib/Server.js
@@ -35,18 +35,15 @@ class Server {
     // Keep track of websocket proxies for external websocket upgrade.
     this.webSocketProxies = [];
     this.sockets = [];
-    this.compiler = compiler;
-    
-    if (this.compiler) {
+
+    if (compiler) {
       this.apply(compiler);
     }
   }
 
   apply(compiler) {
-    if (!compiler.compilers) {
-      this.start();
-    }
-
+    this.compiler = compiler;
+    this.start();
   }
 
   static get DEFAULT_STATS() {

From bd23953fbbc32951450ea6042e50b604e9f542e1 Mon Sep 17 00:00:00 2001
From: Rishabh Chawla <rishabh31121999@gmail.com>
Date: Thu, 16 Sep 2021 14:34:02 +0530
Subject: [PATCH 3/9] chore: keep backwards compatibility

---
 lib/Server.js | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lib/Server.js b/lib/Server.js
index 8d0b77a028..7431eddcc4 100644
--- a/lib/Server.js
+++ b/lib/Server.js
@@ -36,8 +36,9 @@ class Server {
     this.webSocketProxies = [];
     this.sockets = [];
 
+    // TODO: remove this after plugin support is published
     if (compiler) {
-      this.apply(compiler);
+      this.compiler = compiler
     }
   }
 

From 50748dabdf25f7eb0ab29f3773ed17b80bab6e90 Mon Sep 17 00:00:00 2001
From: Rishabh Chawla <rishabh31121999@gmail.com>
Date: Fri, 17 Sep 2021 13:40:20 +0530
Subject: [PATCH 4/9] chore: lint server js

---
 lib/Server.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/Server.js b/lib/Server.js
index 7431eddcc4..4803ecc692 100644
--- a/lib/Server.js
+++ b/lib/Server.js
@@ -38,7 +38,7 @@ class Server {
 
     // TODO: remove this after plugin support is published
     if (compiler) {
-      this.compiler = compiler
+      this.compiler = compiler;
     }
   }
 

From cf33c23cf7e49f663e8e09a9f0e51ea2be71e618 Mon Sep 17 00:00:00 2001
From: Rishabh Chawla <rishabh31121999@gmail.com>
Date: Fri, 17 Sep 2021 14:45:25 +0530
Subject: [PATCH 5/9] test: basic plugin support

---
 test/server/Server.test.js | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/test/server/Server.test.js b/test/server/Server.test.js
index db2a5b0ec8..e29aa7352f 100644
--- a/test/server/Server.test.js
+++ b/test/server/Server.test.js
@@ -50,6 +50,17 @@ describe("Server", () => {
       }
     }
 
+    it("should accept plugin API", (done) => {
+      const compiler = webpack(config);
+      const server = new Server(baseDevConfig);
+      server.apply(compiler);
+
+      compiler.hooks.done.tap("webpack-dev-server", () => {
+        expect(true).toBe(true);
+        server.stopCallback(done);
+      });
+    });
+
     it("add hot option", (done) => {
       const compiler = webpack(config);
       const server = new Server({ ...baseDevConfig, hot: true }, compiler);

From c3cd6b702f2c400d3b3c9e8f3e3416746229a4f1 Mon Sep 17 00:00:00 2001
From: Rishabh Chawla <rishabh31121999@gmail.com>
Date: Tue, 21 Sep 2021 11:12:21 +0530
Subject: [PATCH 6/9] test: add e2e test for plugin API

---
 .../__snapshots__/api.test.js.snap.webpack5   | 11 +++++++
 test/e2e/api.test.js                          | 32 +++++++++++++++++++
 2 files changed, 43 insertions(+)

diff --git a/test/e2e/__snapshots__/api.test.js.snap.webpack5 b/test/e2e/__snapshots__/api.test.js.snap.webpack5
index b99c7ef97c..a5e2ac7591 100644
--- a/test/e2e/__snapshots__/api.test.js.snap.webpack5
+++ b/test/e2e/__snapshots__/api.test.js.snap.webpack5
@@ -87,3 +87,14 @@ Array [
 `;
 
 exports[`API should work with deprecated API (the order of the arguments in the constructor): page errors 1`] = `Array []`;
+
+exports[`API should work with plugin API: console messages 1`] = `
+Array [
+  "[HMR] Waiting for update signal from WDS...",
+  "Hey.",
+  "[webpack-dev-server] Hot Module Replacement enabled.",
+  "[webpack-dev-server] Live Reloading enabled.",
+]
+`;
+
+exports[`API should work with plugin API: page errors 1`] = `Array []`;
diff --git a/test/e2e/api.test.js b/test/e2e/api.test.js
index a361ecfc87..e7ae5c213b 100644
--- a/test/e2e/api.test.js
+++ b/test/e2e/api.test.js
@@ -8,6 +8,38 @@ const runBrowser = require("../helpers/run-browser");
 const port = require("../ports-map").api;
 
 describe("API", () => {
+  it(`should work with plugin API`, async () => {
+    const compiler = webpack(config);
+    const server = new Server({ port });
+
+    server.apply(compiler);
+
+    const { page, browser } = await runBrowser();
+
+    const pageErrors = [];
+    const consoleMessages = [];
+
+    page
+      .on("console", (message) => {
+        consoleMessages.push(message);
+      })
+      .on("pageerror", (error) => {
+        pageErrors.push(error);
+      });
+
+    await page.goto(`http://127.0.0.1:${port}/main`, {
+      waitUntil: "networkidle0",
+    });
+
+    expect(consoleMessages.map((message) => message.text())).toMatchSnapshot(
+      "console messages"
+    );
+    expect(pageErrors).toMatchSnapshot("page errors");
+
+    await browser.close();
+    await server.stop();
+  });
+
   it(`should work with async API`, async () => {
     const compiler = webpack(config);
     const server = new Server({ port }, compiler);

From 9d35ac4729d34807914bca48ccb7980274fc69c9 Mon Sep 17 00:00:00 2001
From: Rishabh Chawla <rishabh31121999@gmail.com>
Date: Tue, 21 Sep 2021 11:33:21 +0530
Subject: [PATCH 7/9] chore: remove comment

---
 lib/Server.js | 1 -
 1 file changed, 1 deletion(-)

diff --git a/lib/Server.js b/lib/Server.js
index 1f0f42afb6..7d891511b0 100644
--- a/lib/Server.js
+++ b/lib/Server.js
@@ -36,7 +36,6 @@ class Server {
     this.webSocketProxies = [];
     this.sockets = [];
 
-    // TODO: remove this after plugin support is published
     if (compiler) {
       this.compiler = compiler;
     }

From dc9075c45d271a8c8a018cce711ed5fbdd46ec59 Mon Sep 17 00:00:00 2001
From: Rishabh Chawla <rishabh31121999@gmail.com>
Date: Tue, 21 Sep 2021 11:53:12 +0530
Subject: [PATCH 8/9] chore: update snapshot for webpack 4

---
 test/e2e/__snapshots__/api.test.js.snap.webpack4 | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/test/e2e/__snapshots__/api.test.js.snap.webpack4 b/test/e2e/__snapshots__/api.test.js.snap.webpack4
index b99c7ef97c..a5e2ac7591 100644
--- a/test/e2e/__snapshots__/api.test.js.snap.webpack4
+++ b/test/e2e/__snapshots__/api.test.js.snap.webpack4
@@ -87,3 +87,14 @@ Array [
 `;
 
 exports[`API should work with deprecated API (the order of the arguments in the constructor): page errors 1`] = `Array []`;
+
+exports[`API should work with plugin API: console messages 1`] = `
+Array [
+  "[HMR] Waiting for update signal from WDS...",
+  "Hey.",
+  "[webpack-dev-server] Hot Module Replacement enabled.",
+  "[webpack-dev-server] Live Reloading enabled.",
+]
+`;
+
+exports[`API should work with plugin API: page errors 1`] = `Array []`;

From 85d443a0a14e70256298863dc98dbbbc8e67b60b Mon Sep 17 00:00:00 2001
From: evilebottnawi <sheo13666q@gmail.com>
Date: Tue, 21 Sep 2021 22:20:33 +0300
Subject: [PATCH 9/9] fix: plugin usage

---
 lib/Server.js | 33 ++++++++++++++++++++++-----------
 1 file changed, 22 insertions(+), 11 deletions(-)

diff --git a/lib/Server.js b/lib/Server.js
index 7d891511b0..49b5fd97f6 100644
--- a/lib/Server.js
+++ b/lib/Server.js
@@ -15,6 +15,8 @@ if (!process.env.WEBPACK_SERVE) {
   process.env.WEBPACK_SERVE = true;
 }
 
+const pluginName = "webpack-dev-server";
+
 class Server {
   constructor(options = {}, compiler) {
     // TODO: remove this after plugin support is published
@@ -41,11 +43,6 @@ class Server {
     }
   }
 
-  apply(compiler) {
-    this.compiler = compiler;
-    this.start();
-  }
-
   static get DEFAULT_STATS() {
     return {
       all: false,
@@ -134,6 +131,20 @@ class Server {
     return path.resolve(dir, "node_modules/.cache/webpack-dev-server");
   }
 
+  apply(compiler) {
+    this.compiler = compiler;
+
+    let started = false;
+
+    compiler.hooks.watchRun.tapPromise(pluginName, async () => {
+      if (!started) {
+        await this.start();
+
+        started = true;
+      }
+    });
+  }
+
   addAdditionalEntries(compiler) {
     const additionalEntries = [];
 
@@ -403,7 +414,7 @@ class Server {
     const { options } = this;
 
     if (!this.logger) {
-      this.logger = this.compiler.getInfrastructureLogger("webpack-dev-server");
+      this.logger = this.compiler.getInfrastructureLogger(pluginName);
     }
 
     const compilerOptions = this.getCompilerOptions();
@@ -696,7 +707,7 @@ class Server {
     if (typeof options.ipc === "boolean") {
       const isWindows = process.platform === "win32";
       const pipePrefix = isWindows ? "\\\\.\\pipe\\" : os.tmpdir();
-      const pipeName = "webpack-dev-server.sock";
+      const pipeName = `${pluginName}.sock`;
 
       options.ipc = path.join(pipePrefix, pipeName);
     }
@@ -1158,12 +1169,12 @@ class Server {
   }
 
   setupHooks() {
-    this.compiler.hooks.invalid.tap("webpack-dev-server", () => {
+    this.compiler.hooks.invalid.tap(pluginName, () => {
       if (this.webSocketServer) {
         this.sendMessage(this.webSocketServer.clients, "invalid");
       }
     });
-    this.compiler.hooks.done.tap("webpack-dev-server", (stats) => {
+    this.compiler.hooks.done.tap(pluginName, (stats) => {
       if (this.webSocketServer) {
         this.sendStats(this.webSocketServer.clients, this.getStats(stats));
       }
@@ -2146,7 +2157,7 @@ class Server {
     }
   }
 
-  startCallback(callback) {
+  startCallback(callback = () => {}) {
     this.start().then(() => callback(null), callback);
   }
 
@@ -2218,7 +2229,7 @@ class Server {
       "DEP_WEBPACK_DEV_SERVER_LISTEN"
     )();
 
-    this.logger = this.compiler.getInfrastructureLogger("webpack-dev-server");
+    this.logger = this.compiler.getInfrastructureLogger(pluginName);
 
     if (typeof port === "function") {
       fn = port;