Skip to content

Commit c8cb8e2

Browse files
committed
docs(plugin): add watch mode plugin example with modifiedFiles and fileDependencies
1 parent cc75d21 commit c8cb8e2

1 file changed

Lines changed: 59 additions & 0 deletions

File tree

src/content/contribute/writing-a-plugin.mdx

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,65 @@ T> We are using synchronous `tap()` method to tap into the `processAssets` hook
300300

301301
T> The [`processAssets`](/api/compilation-hooks/#processassets) hook also supports the `additionalAssets` property, that allows your plugin to intercept not only assets that were added by other plugins prior to the execution of the specified stage, but also for assets that were added on a later stages. This allows to intercept absolutely all the assets which are part of the compilation. However, in our example we are fine with using the `SUMMARIZE` stage to capture all the assets generated on previous stages (this should account for all assets in general case).
302302

303+
## Watching for file changes
304+
305+
When webpack runs in watch mode (`webpack --watch` or `devServer`),
306+
Webpack creates a new compilation for each rebuild triggered by file changes.
307+
308+
The `compiler.modifiedFiles` Set lets your plugin know **which specific
309+
files triggered the rebuild**, so you can skip expensive work for unrelated files.
310+
311+
This is useful for plugins that need to react only to specific file changes
312+
(e.g., regenerating assets, reprocessing templates, or invalidating caches).
313+
314+
```js
315+
class WatchNotifierPlugin {
316+
apply(compiler) {
317+
compiler.hooks.watchRun.tap('WatchNotifierPlugin', (compiler) => {
318+
if (compiler.modifiedFiles) {
319+
const changedFiles = Array.from(compiler.modifiedFiles)
320+
.map((file) => `${file}`)
321+
.join('\n');
322+
323+
console.log(`\nFiles changed:\n${changedFiles}`);
324+
}
325+
});
326+
}
327+
}
328+
329+
module.exports = WatchNotifierPlugin;
330+
```
331+
> **Note**:
332+
> - `compiler.modifiedFiles` is a `Set`, not an array
333+
> - It is `undefined` on the first (cold) build
334+
> - It is only populated during watch rebuilds
335+
336+
### Adding custom file dependencies
337+
338+
If your plugin reads external files (config files, templates, etc.)
339+
that webpack does not track by default, you must tell webpack to watch them.
340+
341+
The `compilation.fileDependencies` set allows you to add such files.
342+
343+
```js
344+
const path = require('path');
345+
346+
class TemplateWatchPlugin {
347+
apply(compiler) {
348+
compiler.hooks.compilation.tap('TemplateWatchPlugin', (compilation) => {
349+
const templatePath = path.resolve(__dirname, 'my-template.html');
350+
351+
// Ensure webpack watches this file
352+
compilation.fileDependencies.add(templatePath);
353+
});
354+
}
355+
}
356+
357+
module.exports = TemplateWatchPlugin;
358+
```
359+
Without calling `fileDependencies.add()`, webpack will not trigger
360+
a rebuild when the file changes — even if your plugin depends on it.
361+
303362
## Different Plugin Shapes
304363

305364
A plugin can be classified into types based on the event hooks it taps into. Every event hook is pre-defined as synchronous or asynchronous or waterfall or parallel hook and hook is called internally using call/callAsync method. The list of hooks that are supported or can be tapped into is generally specified in `this.hooks` property.

0 commit comments

Comments
 (0)