0

我正在开发一个 Webpack 5 插件,我需要手动触发对监视文件的重新编译而不修改它(主要是做一些利基 HMR 的东西)。

我认为最简单的方法是让编译器相信文件已更改。我不想用fs实际更改文件。我查看了 webpack 源代码 - 欺骗 webpack 的NodeWatchFileSystem看起来很hacky。以另一种方式触发重新编译超出了我的范围。

4

2 回答 2

1

一直追溯到文件观察器,当保存文件时,文件观察器发出“更改”事件,随后的函数使用此事件并触发更改文件的重新编译。

由于我们需要“更改”事件和重新编译,但对于未更改的文件,访问这些消费者函数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"
  );

于 2021-08-15T13:19:15.633 回答
0

重新编译监视文件(实际上不改变)的最简单方法是更新它们的时间戳并将它们添加到 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');
});
于 2021-05-24T22:07:37.413 回答