WatchIgnorePlugin.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const { groupBy } = require("./util/ArrayHelpers");
  7. const createSchemaValidation = require("./util/create-schema-validation");
  8. /** @typedef {import("../declarations/plugins/WatchIgnorePlugin").WatchIgnorePluginOptions} WatchIgnorePluginOptions */
  9. /** @typedef {import("./Compiler")} Compiler */
  10. /** @typedef {import("./util/fs").WatchFileSystem} WatchFileSystem */
  11. const validate = createSchemaValidation(
  12. require("../schemas/plugins/WatchIgnorePlugin.check.js"),
  13. () => require("../schemas/plugins/WatchIgnorePlugin.json"),
  14. {
  15. name: "Watch Ignore Plugin",
  16. baseDataPath: "options"
  17. }
  18. );
  19. const IGNORE_TIME_ENTRY = "ignore";
  20. class IgnoringWatchFileSystem {
  21. /**
  22. * @param {WatchFileSystem} wfs original file system
  23. * @param {(string|RegExp)[]} paths ignored paths
  24. */
  25. constructor(wfs, paths) {
  26. this.wfs = wfs;
  27. this.paths = paths;
  28. }
  29. watch(files, dirs, missing, startTime, options, callback, callbackUndelayed) {
  30. files = Array.from(files);
  31. dirs = Array.from(dirs);
  32. const ignored = path =>
  33. this.paths.some(p =>
  34. p instanceof RegExp ? p.test(path) : path.indexOf(p) === 0
  35. );
  36. const [ignoredFiles, notIgnoredFiles] = groupBy(files, ignored);
  37. const [ignoredDirs, notIgnoredDirs] = groupBy(dirs, ignored);
  38. const watcher = this.wfs.watch(
  39. notIgnoredFiles,
  40. notIgnoredDirs,
  41. missing,
  42. startTime,
  43. options,
  44. (err, fileTimestamps, dirTimestamps, changedFiles, removedFiles) => {
  45. if (err) return callback(err);
  46. for (const path of ignoredFiles) {
  47. fileTimestamps.set(path, IGNORE_TIME_ENTRY);
  48. }
  49. for (const path of ignoredDirs) {
  50. dirTimestamps.set(path, IGNORE_TIME_ENTRY);
  51. }
  52. callback(
  53. err,
  54. fileTimestamps,
  55. dirTimestamps,
  56. changedFiles,
  57. removedFiles
  58. );
  59. },
  60. callbackUndelayed
  61. );
  62. return {
  63. close: () => watcher.close(),
  64. pause: () => watcher.pause(),
  65. getContextTimeInfoEntries: () => {
  66. const dirTimestamps = watcher.getContextTimeInfoEntries();
  67. for (const path of ignoredDirs) {
  68. dirTimestamps.set(path, IGNORE_TIME_ENTRY);
  69. }
  70. return dirTimestamps;
  71. },
  72. getFileTimeInfoEntries: () => {
  73. const fileTimestamps = watcher.getFileTimeInfoEntries();
  74. for (const path of ignoredFiles) {
  75. fileTimestamps.set(path, IGNORE_TIME_ENTRY);
  76. }
  77. return fileTimestamps;
  78. },
  79. getInfo:
  80. watcher.getInfo &&
  81. (() => {
  82. const info = watcher.getInfo();
  83. const { fileTimeInfoEntries, contextTimeInfoEntries } = info;
  84. for (const path of ignoredFiles) {
  85. fileTimeInfoEntries.set(path, IGNORE_TIME_ENTRY);
  86. }
  87. for (const path of ignoredDirs) {
  88. contextTimeInfoEntries.set(path, IGNORE_TIME_ENTRY);
  89. }
  90. return info;
  91. })
  92. };
  93. }
  94. }
  95. class WatchIgnorePlugin {
  96. /**
  97. * @param {WatchIgnorePluginOptions} options options
  98. */
  99. constructor(options) {
  100. validate(options);
  101. this.paths = options.paths;
  102. }
  103. /**
  104. * Apply the plugin
  105. * @param {Compiler} compiler the compiler instance
  106. * @returns {void}
  107. */
  108. apply(compiler) {
  109. compiler.hooks.afterEnvironment.tap("WatchIgnorePlugin", () => {
  110. compiler.watchFileSystem = new IgnoringWatchFileSystem(
  111. compiler.watchFileSystem,
  112. this.paths
  113. );
  114. });
  115. }
  116. }
  117. module.exports = WatchIgnorePlugin;