Reputation: 78
I'm developing a Webpack 5 plugin and I need to manually trigger a recompile on a watched file without modifying it (mainly to do some niche HMR stuff).
I figure the easiest way is to convince the compiler that the file has changed. I don't want to actually change the file with fs. I've looked into the webpack source code - spoofing webpack's NodeWatchFileSystem looks to be very hacky. Triggering a recompile another way is beyond me.
Upvotes: 0
Views: 1270
Reputation: 81
Tracing backwards all the way to the file watchers, when a file is saved, the file watcher emits the "change" event and the functions that follow consume this event and trigger the recompilation for the changed file.
As we require a "change" event and a recompilation, but for an unchanged file, accessing these consumer functions (setFileTime(...)
) & simulating the consumption of a "change" event would be a cleaner solution like below, worked great for me!
//unchanged file that needs to be recompiled
let filePath = "/Users/my-project/src/HelloWorld.js"
// Webpack v5.x
compiler.watchFileSystem.watcher.fileWatchers
.get(filePath)
.directoryWatcher.setFileTime(
filePath,
new Date().getTime(),
false,
false,
"change"
);
// Webpack v4.x
compiler.watchFileSystem.watcher.fileWatchers
.find((watcher) => watcher.path === filePath)
.directoryWatcher.setFileTime(
filePath,
new Date().getTime(),
false,
"change"
);
Upvotes: 3
Reputation: 78
The simplest way to recompile watched files (without them actually changing) is to update their timestamps and add them to the modified files on the webpack compiler. Then, invalidating watching
, making sure to clear the watcher
first.
This will trigger a new build on just those files, running all loaders, and updating HMR, etc.
const time = Date.now();
const timestamps = new Map<string, FileSystemInfoEntry>();
const modifiedFiles = new Set<string>();
// Make an entry for each file path that should recompile
paths.forEach(path => {
timestamps.set(path, {
safeTime: time,
timestamp: time,
// accuracy: 0,
});
modifiedFiles.add(path);
});
compiler.fileTimestamps = timestamps;
compiler.contextTimestamps = timestamps;
compiler.modifiedFiles = modifiedFiles;
// Trigger recompile
compiler.watching.watcher = null; // Otherwise watcher will pull in fresh file data, undoing the compiler modifications above
compiler.watching.invalidate(() => { // Triggers the recompile
console.log('Recompile finished');
});
Upvotes: 1