Skip to content

Commit 13d0398

Browse files
committed
feat: enhance watchFiles option to support ignored patterns with glob strings
1 parent 6869880 commit 13d0398

File tree

3 files changed

+143
-6
lines changed

3 files changed

+143
-6
lines changed

lib/Server.js

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3190,12 +3190,24 @@ class Server {
31903190
const chokidar = require("chokidar");
31913191
const { globSync, isDynamicPattern } = require("tinyglobby");
31923192

3193-
const paths = Array.isArray(watchPath) ? watchPath : [watchPath];
3194-
const resolvedPaths = paths.flatMap((path) =>
3195-
isDynamicPattern(path)
3196-
? globSync(path, { cwd: watchOptions.cwd, absolute: true })
3197-
: path,
3198-
);
3193+
const resolveGlobs = (/** @type {string | string[]} */ input) =>
3194+
(Array.isArray(input) ? input : [input]).flatMap((path) =>
3195+
typeof path === "string" && isDynamicPattern(path)
3196+
? globSync(path, { cwd: watchOptions.cwd, absolute: true })
3197+
: path,
3198+
);
3199+
3200+
const resolvedPaths = resolveGlobs(watchPath);
3201+
3202+
if (typeof watchOptions.ignored === "string") {
3203+
watchOptions.ignored = resolveGlobs(watchOptions.ignored);
3204+
} else if (Array.isArray(watchOptions.ignored)) {
3205+
watchOptions.ignored = watchOptions.ignored.flatMap((item) =>
3206+
typeof item === "string" && isDynamicPattern(item)
3207+
? globSync(item, { cwd: watchOptions.cwd, absolute: true })
3208+
: item,
3209+
);
3210+
}
31993211

32003212
const watcher = chokidar.watch(resolvedPaths, watchOptions);
32013213

test/e2e/__snapshots__/watch-files.test.js.snap.webpack5

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,18 @@ exports[`watchFiles option should work with directory and ignored option to filt
4242

4343
exports[`watchFiles option should work with directory and ignored option to filter files should reload when file content is changed: response status 1`] = `200`;
4444

45+
exports[`watchFiles option should work with ignored option using glob string should not reload when an ignored glob file is changed: response status 1`] = `200`;
46+
47+
exports[`watchFiles option should work with ignored option using glob string should reload when file content is changed: console messages 1`] = `
48+
[
49+
"Hey.",
50+
]
51+
`;
52+
53+
exports[`watchFiles option should work with ignored option using glob string should reload when file content is changed: page errors 1`] = `[]`;
54+
55+
exports[`watchFiles option should work with ignored option using glob string should reload when file content is changed: response status 1`] = `200`;
56+
4557
exports[`watchFiles option should work with object with multiple paths should reload when file content is changed: console messages 1`] = `
4658
[
4759
"Hey.",

test/e2e/watch-files.test.js

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,119 @@ describe("watchFiles option", () => {
415415
});
416416
});
417417

418+
describe("should work with ignored option using glob string", () => {
419+
const file = path.join(watchDir, "assets/example.txt");
420+
const ignoredFile = path.join(watchDir, "assets/example.js");
421+
let compiler;
422+
let server;
423+
let page;
424+
let browser;
425+
let pageErrors;
426+
let consoleMessages;
427+
428+
beforeEach(async () => {
429+
compiler = webpack(config);
430+
431+
server = new Server(
432+
{
433+
watchFiles: {
434+
paths: watchDir,
435+
options: {
436+
ignored: `${watchDir}/**/*.js`,
437+
},
438+
},
439+
port,
440+
},
441+
compiler,
442+
);
443+
444+
await server.start();
445+
446+
({ page, browser } = await runBrowser());
447+
448+
pageErrors = [];
449+
consoleMessages = [];
450+
});
451+
452+
afterEach(async () => {
453+
await browser.close();
454+
await server.stop();
455+
fs.truncateSync(file);
456+
});
457+
458+
it("should reload when file content is changed", async () => {
459+
page
460+
.on("console", (message) => {
461+
consoleMessages.push(message);
462+
})
463+
.on("pageerror", (error) => {
464+
pageErrors.push(error);
465+
});
466+
467+
const response = await page.goto(`http://localhost:${port}/`, {
468+
waitUntil: "networkidle0",
469+
});
470+
471+
expect(response.status()).toMatchSnapshot("response status");
472+
473+
expect(consoleMessages.map((message) => message.text())).toMatchSnapshot(
474+
"console messages",
475+
);
476+
477+
expect(pageErrors).toMatchSnapshot("page errors");
478+
479+
// change file content
480+
fs.writeFileSync(file, "Kurosaki Ichigo", "utf8");
481+
482+
await new Promise((resolve) => {
483+
server.staticWatchers[0].on("change", async (changedPath) => {
484+
// page reload
485+
await page.waitForNavigation({ waitUntil: "networkidle0" });
486+
487+
expect(changedPath).toBe(file);
488+
489+
resolve();
490+
});
491+
});
492+
});
493+
494+
it("should not reload when an ignored glob file is changed", async () => {
495+
page
496+
.on("console", (message) => {
497+
consoleMessages.push(message);
498+
})
499+
.on("pageerror", (error) => {
500+
pageErrors.push(error);
501+
});
502+
503+
const response = await page.goto(`http://localhost:${port}/`, {
504+
waitUntil: "networkidle0",
505+
});
506+
507+
expect(response.status()).toMatchSnapshot("response status");
508+
509+
// change ignored file content
510+
fs.writeFileSync(ignoredFile, "// changed", "utf8");
511+
512+
// wait a bit to ensure no reload happens
513+
await new Promise((resolve) => {
514+
let changed = false;
515+
516+
server.staticWatchers[0].on("change", () => {
517+
changed = true;
518+
});
519+
520+
setTimeout(() => {
521+
expect(changed).toBe(false);
522+
resolve();
523+
}, 2000);
524+
});
525+
526+
// restore file
527+
fs.writeFileSync(ignoredFile, "// test file\n", "utf8");
528+
});
529+
});
530+
418531
describe("should not crash if file doesn't exist", () => {
419532
const nonExistFile = path.join(watchDir, "assets/non-exist.txt");
420533
let compiler;

0 commit comments

Comments
 (0)