Может ли webpack сообщить, какой файл вызвал компиляцию в режиме просмотра?

Я хотел бы, чтобы Webpack регистрировал, какой файл вызвал мою сборку в режиме просмотра.

Я настроил плагин, который прослушивает хук событий компилятора watch-run следующим образом:

function() {
  this.plugin("watch-run", function(watching, callback) {
    // maybe something in `watching` will indicate the changed file?
    // when I find out what it is, `console.log` it here
    callback();
  });
}

// Example output: "/Users/aaron/git/test/index.js" was changed, new build triggered

Но я не могу понять, где может быть измененная информация о файле, если она вообще есть.

Документации Webpack действительно не хватает в этой области. На странице перехватчик событий компилятора нет примеров (только сообщение, поясняющее, что скоро появятся примеры), а старая документация v1 не гораздо лучше при разработке свойств/методов, доступных в объекте watching/compiler.

Любая помощь или руководство будет принята с благодарностью.


person Aaron Cunnington    schedule 31.03.2017    source источник


Ответы (4)


Такого рода информация не содержится в документации веб-пакета, и было бы сложно включить все возможные опции, доступные в компиляторе. Но я бы сказал, что это та область, где вы должны изучить доступные варианты, либо прочитав исходный код, либо запустив отладчик и изучив их. Я сделал последнее и обнаружил, что измененные файлы доступны в:

watching.compiler.watchFileSystem.watcher.mtimes

Это объект, в котором каждый ключ является абсолютным путем к файлу, который был изменен, а значением является отметка времени, когда он был изменен. Возможно иметь более одного изменения файла, которое запускает перекомпиляцию, когда несколько изменений были сохранены в течение настроенного интервала опроса.

Следующий код выводит измененные файлы (файлы также могут быть пустыми):

this.plugin("watch-run", (watching, done) => {
  const changedTimes = watching.compiler.watchFileSystem.watcher.mtimes;
  const changedFiles = Object.keys(changedTimes)
    .map(file => `\n  ${file}`)
    .join("");
  if (changedFiles.length) {
    console.log("New build triggered, files changed:", changedFiles);
  }
  done();
});

Пример вывода:

New build triggered, files changed:
  /path/to/app/src/components/item/Item.js
  /path/to/app/src/App.js

Примечание. Этот вывод появится до того, как будет напечатана окончательная статистика.

person Michael Jungo    schedule 31.03.2017
comment
Спасибо, что поделились этой информацией... Ваш код позволил мне выяснить причину непрерывной непрерывной перестройки HMR в моем проекте, вызванную случайным файлом .html, созданным модулем покрытия кода. - person David Chelliah; 27.11.2017

Плагин, который я использовал для этого в Webpack 4:

class WatchRunPlugin {
  apply(compiler) {
    compiler.hooks.watchRun.tap('WatchRun', (comp) => {
      const changedTimes = comp.watchFileSystem.watcher.mtimes;
      const changedFiles = Object.keys(changedTimes)
        .map(file => `\n  ${file}`)
        .join('');
      if (changedFiles.length) {
        console.log("====================================")
        console.log('NEW BUILD FILES CHANGED:', changedFiles);
        console.log("====================================")
      }
    });
  }
}
person sander    schedule 13.03.2019
comment
Потрясающие. Я использую смесь Laravel, и по какой-то причине мне пришлось добавить конструктор constructor() {}, чтобы это работало. - person Colin Claverie; 09.05.2019
comment
Если это не работает, взгляните на ответ ниже, в котором используется второй аргумент done (или callback в документах). Я не мог заставить это работать, не вызывая обратный вызов в конце. stackoverflow.com/a/52363168/697745. С обратным вызовом это работает хорошо. - person Dol; 12.02.2020
comment
Я просто копирую это в тип моего файла webpack.config.js, затем добавляю new WatchRunPlugin() к своим плагинам и... Боб твой дядя. - person Jeremy John; 09.07.2020
comment
Если вы используете WatchIgnorePlugin, вам нужно: const watcher = comp.watchFileSystem.wfs ? comp.watchFileSystem.wfs.watcher : comp.watchFileSystem.watcher; const changedTimes = watcher.mtimes; - person Jeremy John; 10.07.2020

Для Webpack 5, поскольку watchFileSystem.watcher.mtimes был удален, я изменил отличный ответ от @sander на это:

class WatchRunPlugin {
    apply(compiler) {
        compiler.hooks.watchRun.tap('WatchRun', (comp) => {
            if (comp.modifiedFiles) {
                const changedFiles = Array.from(comp.modifiedFiles, (file) => `\n  ${file}`).join('');
                console.log('===============================');
                console.log('FILES CHANGED:', changedFiles);
                console.log('===============================');
            }
        });
    }
}
person Schweinepriester    schedule 28.10.2020

В веб-пакете 4 вы можете получить доступ к watcher таким образом:

getChangedFiles(compiler) {
  const { watchFileSystem } = compiler;
  const watcher = watchFileSystem.watcher || watchFileSystem.wfs.watcher;

  return Object.keys(watcher.mtimes);
}

последний в хуке watchRun

compiler.hooks.watchRun.tapAsync('plugin name', (_compiler, done) => {
  const changedFile = this.getChangedFiles(_compiler)

  // ...

  return done();
});
person Marcin    schedule 17.09.2018