CachePlugin.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const asyncLib = require("neo-async");
  7. class CachePlugin {
  8. constructor(cache) {
  9. this.cache = cache || {};
  10. this.FS_ACCURACY = 2000;
  11. }
  12. apply(compiler) {
  13. if (Array.isArray(compiler.compilers)) {
  14. compiler.compilers.forEach((c, idx) => {
  15. new CachePlugin((this.cache[idx] = this.cache[idx] || {})).apply(c);
  16. });
  17. } else {
  18. const registerCacheToCompiler = (compiler, cache) => {
  19. compiler.hooks.thisCompilation.tap("CachePlugin", compilation => {
  20. compilation.cache = cache;
  21. compilation.hooks.childCompiler.tap(
  22. "CachePlugin",
  23. (childCompiler, compilerName, compilerIndex) => {
  24. if (cache) {
  25. let childCache;
  26. if (!cache.children) {
  27. cache.children = {};
  28. }
  29. if (!cache.children[compilerName]) {
  30. cache.children[compilerName] = [];
  31. }
  32. if (cache.children[compilerName][compilerIndex]) {
  33. childCache = cache.children[compilerName][compilerIndex];
  34. } else {
  35. cache.children[compilerName].push((childCache = {}));
  36. }
  37. registerCacheToCompiler(childCompiler, childCache);
  38. }
  39. }
  40. );
  41. });
  42. };
  43. registerCacheToCompiler(compiler, this.cache);
  44. compiler.hooks.watchRun.tap("CachePlugin", () => {
  45. this.watching = true;
  46. });
  47. compiler.hooks.run.tapAsync("CachePlugin", (compiler, callback) => {
  48. if (!compiler._lastCompilationFileDependencies) {
  49. return callback();
  50. }
  51. const fs = compiler.inputFileSystem;
  52. const fileTs = (compiler.fileTimestamps = new Map());
  53. asyncLib.forEach(
  54. compiler._lastCompilationFileDependencies,
  55. (file, callback) => {
  56. fs.stat(file, (err, stat) => {
  57. if (err) {
  58. if (err.code === "ENOENT") return callback();
  59. return callback(err);
  60. }
  61. if (stat.mtime) this.applyMtime(+stat.mtime);
  62. fileTs.set(file, +stat.mtime || Infinity);
  63. callback();
  64. });
  65. },
  66. err => {
  67. if (err) return callback(err);
  68. for (const [file, ts] of fileTs) {
  69. fileTs.set(file, ts + this.FS_ACCURACY);
  70. }
  71. callback();
  72. }
  73. );
  74. });
  75. compiler.hooks.afterCompile.tap("CachePlugin", compilation => {
  76. compilation.compiler._lastCompilationFileDependencies =
  77. compilation.fileDependencies;
  78. compilation.compiler._lastCompilationContextDependencies =
  79. compilation.contextDependencies;
  80. });
  81. }
  82. }
  83. /* istanbul ignore next */
  84. applyMtime(mtime) {
  85. if (this.FS_ACCURACY > 1 && mtime % 2 !== 0) this.FS_ACCURACY = 1;
  86. else if (this.FS_ACCURACY > 10 && mtime % 20 !== 0) this.FS_ACCURACY = 10;
  87. else if (this.FS_ACCURACY > 100 && mtime % 200 !== 0)
  88. this.FS_ACCURACY = 100;
  89. else if (this.FS_ACCURACY > 1000 && mtime % 2000 !== 0)
  90. this.FS_ACCURACY = 1000;
  91. }
  92. }
  93. module.exports = CachePlugin;