diff --git a/lib/Server.js b/lib/Server.js index 8193582d8f..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 @@ -35,7 +37,10 @@ class Server { // Keep track of websocket proxies for external websocket upgrade. this.webSocketProxies = []; this.sockets = []; - this.compiler = compiler; + + if (compiler) { + this.compiler = compiler; + } } static get DEFAULT_STATS() { @@ -126,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 = []; @@ -395,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(); @@ -688,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); } @@ -1150,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)); } @@ -2138,7 +2157,7 @@ class Server { } } - startCallback(callback) { + startCallback(callback = () => {}) { this.start().then(() => callback(null), callback); } @@ -2210,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; 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 []`; 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); 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);