Skip to content

Commit 3f5481a

Browse files
committed
refactor: update README and remove redundant standalone server handling in Server class
1 parent fcc45c6 commit 3f5481a

3 files changed

Lines changed: 10 additions & 96 deletions

File tree

examples/api/plugin/README.md

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,9 @@ npx webpack --watch
3838

3939
## Notes
4040

41-
- Use `webpack --watch`, not `webpack serve`. `webpack serve` creates its own
42-
standalone dev server; if you also have a plugin instance in `plugins[]`,
43-
the plugin detects the standalone server and stays passive to avoid binding
44-
the same port twice.
45-
- A plain `webpack` build (no watch) will not start the server — the plugin
46-
detects build mode and stays passive so the build can finish and the process
47-
can exit normally.
41+
- The plugin works with both `webpack --watch` and `webpack serve`. With
42+
`webpack serve`, `webpack-cli` already creates its own standalone dev server
43+
for the same compiler, so you would end up with two servers running. If
44+
that's intentional (e.g. different ports/hosts), make sure the plugin's
45+
`port` does not clash with the one `webpack-cli` resolves from
46+
`config.devServer` and CLI args. Otherwise prefer one or the other.

lib/Server.js

Lines changed: 4 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -328,20 +328,6 @@ const DEFAULT_ALLOWED_PROTOCOLS = /^(file|.+-extension):/i;
328328

329329
const pluginName = "webpack-dev-server";
330330

331-
/**
332-
* Tracks compilers that have an active standalone `Server` attached
333-
* (`new Server(options, compiler).start()`). When a compiler is in this set,
334-
* any `Server` plugin attached to it (or to a `MultiCompiler` that contains
335-
* it) stays passive — otherwise we'd try to bind the same port twice.
336-
* Particularly relevant for `webpack serve`, which creates its own standalone
337-
* server even when the user already added a `Server` instance to `plugins[]`.
338-
*
339-
* Uses a `WeakSet` so a compiler that is no longer referenced anywhere can be
340-
* garbage collected normally, without this module holding it alive.
341-
* @type {WeakSet<Compiler | MultiCompiler>}
342-
*/
343-
const activeStandaloneCompilers = new WeakSet();
344-
345331
/**
346332
* @template {BasicApplication} [A=ExpressApplication]
347333
* @template {BasicServer} [S=HTTPServer]
@@ -3374,36 +3360,8 @@ class Server {
33743360
* @returns {Promise<void>}
33753361
*/
33763362
async start() {
3377-
this.#trackStandalone(true);
3378-
try {
3379-
await this.setup();
3380-
await this.listen();
3381-
} catch (error) {
3382-
this.#trackStandalone(false);
3383-
throw error;
3384-
}
3385-
}
3386-
3387-
/**
3388-
* @param {boolean} active whether to mark or unmark the compiler(s) as
3389-
* having an active standalone server
3390-
* @returns {void}
3391-
*/
3392-
#trackStandalone(active) {
3393-
if (!this.compiler) return;
3394-
const compilers = /** @type {MultiCompiler} */ (this.compiler)
3395-
.compilers || [this.compiler];
3396-
if (active) {
3397-
activeStandaloneCompilers.add(this.compiler);
3398-
for (const child of compilers) {
3399-
activeStandaloneCompilers.add(child);
3400-
}
3401-
} else {
3402-
activeStandaloneCompilers.delete(this.compiler);
3403-
for (const child of compilers) {
3404-
activeStandaloneCompilers.delete(child);
3405-
}
3406-
}
3363+
await this.setup();
3364+
await this.listen();
34073365
}
34083366

34093367
/**
@@ -3520,8 +3478,6 @@ class Server {
35203478
* @returns {Promise<void>}
35213479
*/
35223480
async stop() {
3523-
this.#trackStandalone(false);
3524-
35253481
if (this.bonjour) {
35263482
await /** @type {Promise<void>} */ (
35273483
new Promise((resolve) => {
@@ -3642,21 +3598,6 @@ class Server {
36423598
const seenFirstDone = new WeakSet();
36433599
let firstDoneCount = 0;
36443600

3645-
// Returns true when a standalone `Server` is already attached to our
3646-
// compiler (or any of its children). This matters for `webpack serve`:
3647-
// it creates its own standalone server even if the user added a `Server`
3648-
// instance to `plugins[]`. In that case the plugin must stay passive —
3649-
// otherwise we'd try to bind the same port twice. Independent
3650-
// server/compiler pairs in the same process are unaffected because they
3651-
// don't share any compiler instance.
3652-
const isStandaloneRunning = () => {
3653-
if (activeStandaloneCompilers.has(compiler)) return true;
3654-
for (const child of childCompilers) {
3655-
if (activeStandaloneCompilers.has(child)) return true;
3656-
}
3657-
return false;
3658-
};
3659-
36603601
// A one-shot `compiler.run()` (plain `webpack` build) is detected when no
36613602
// child compiler is in watch mode. In that case we skip both `setup()` and
36623603
// `listen()` so the build can finish and the process can exit normally —
@@ -3669,7 +3610,7 @@ class Server {
36693610
* @returns {Promise<void>} promise
36703611
*/
36713612
const ensureSetup = () => {
3672-
if (isStandaloneRunning() || isBuildMode()) return Promise.resolve();
3613+
if (isBuildMode()) return Promise.resolve();
36733614
if (!setupPromise) {
36743615
setupPromise = this.setup();
36753616
}
@@ -3681,7 +3622,7 @@ class Server {
36813622
* @returns {Promise<void>} promise
36823623
*/
36833624
const onChildDone = async (childCompiler) => {
3684-
if (listening || isStandaloneRunning() || isBuildMode()) return;
3625+
if (listening || isBuildMode()) return;
36853626
if (seenFirstDone.has(childCompiler)) return;
36863627
seenFirstDone.add(childCompiler);
36873628
firstDoneCount++;

test/e2e/api-plugin.test.js

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -343,31 +343,5 @@ describe("API (plugin)", () => {
343343
});
344344
}
345345
});
346-
347-
it("should stay passive when a standalone server runs on the same compiler", async () => {
348-
const compiler = webpack(config);
349-
const pluginServer = new Server({ port });
350-
const standaloneServer = new Server({ port }, compiler);
351-
352-
const pluginSetupSpy = jest.spyOn(pluginServer, "setup");
353-
const pluginListenSpy = jest.spyOn(pluginServer, "listen");
354-
355-
pluginServer.apply(compiler);
356-
await standaloneServer.start();
357-
358-
try {
359-
// The standalone server drives compilation through its own
360-
// webpack-dev-middleware. The plugin's hooks fire during that
361-
// compilation but must stay passive — so the plugin's own setup() and
362-
// listen() are never called.
363-
expect(pluginSetupSpy).not.toHaveBeenCalled();
364-
expect(pluginListenSpy).not.toHaveBeenCalled();
365-
} finally {
366-
pluginSetupSpy.mockRestore();
367-
pluginListenSpy.mockRestore();
368-
await standaloneServer.stop();
369-
await pluginServer.stop();
370-
}
371-
});
372346
});
373347
});

0 commit comments

Comments
 (0)