Webpack:在未更改的文件上触发文件监视重新编译
Webpack: Trigger a file watch recompile on an unchanged file
我正在开发一个 Webpack 5 插件,我需要在不修改监视文件的情况下手动触发重新编译(主要是为了做一些小众 HMR 的东西)。
我认为最简单的方法是让编译器相信文件已更改。我不想用 fs 实际更改文件。我查看了 webpack 源代码 - 欺骗 webpack 的 NodeWatchFileSystem 看起来非常 hacky。以另一种方式触发重新编译超出了我的范围。
最简单的重新编译监视文件的方法(不改变它们)是更新它们的时间戳并将它们添加到 webpack 编译器上的修改文件中。然后,使watching
无效,确保先清除watcher
。
这将仅在这些文件、运行 所有加载程序和更新 HMR 等上触发新构建。
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');
});
一直回溯到文件观察器,当一个文件被保存时,文件观察器发出“change”事件,随后的函数使用这个事件并触发对已更改文件的重新编译。
由于我们需要“更改”事件和重新编译,但对于未更改的文件,访问这些消费者函数 (setFileTime(...)
) 并模拟“更改”事件的使用将是一个更简洁的解决方案,例如下面,对我来说非常有用!
//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"
);
我正在开发一个 Webpack 5 插件,我需要在不修改监视文件的情况下手动触发重新编译(主要是为了做一些小众 HMR 的东西)。
我认为最简单的方法是让编译器相信文件已更改。我不想用 fs 实际更改文件。我查看了 webpack 源代码 - 欺骗 webpack 的 NodeWatchFileSystem 看起来非常 hacky。以另一种方式触发重新编译超出了我的范围。
最简单的重新编译监视文件的方法(不改变它们)是更新它们的时间戳并将它们添加到 webpack 编译器上的修改文件中。然后,使watching
无效,确保先清除watcher
。
这将仅在这些文件、运行 所有加载程序和更新 HMR 等上触发新构建。
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');
});
一直回溯到文件观察器,当一个文件被保存时,文件观察器发出“change”事件,随后的函数使用这个事件并触发对已更改文件的重新编译。
由于我们需要“更改”事件和重新编译,但对于未更改的文件,访问这些消费者函数 (setFileTime(...)
) 并模拟“更改”事件的使用将是一个更简洁的解决方案,例如下面,对我来说非常有用!
//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"
);