SizeLimitsPlugin.js 2.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Sean Larkin @thelarkinn
  4. */
  5. "use strict";
  6. const EntrypointsOverSizeLimitWarning = require("./EntrypointsOverSizeLimitWarning");
  7. const AssetsOverSizeLimitWarning = require("./AssetsOverSizeLimitWarning");
  8. const NoAsyncChunksWarning = require("./NoAsyncChunksWarning");
  9. module.exports = class SizeLimitsPlugin {
  10. constructor(options) {
  11. this.hints = options.hints;
  12. this.maxAssetSize = options.maxAssetSize;
  13. this.maxEntrypointSize = options.maxEntrypointSize;
  14. this.assetFilter = options.assetFilter;
  15. }
  16. apply(compiler) {
  17. const entrypointSizeLimit = this.maxEntrypointSize;
  18. const assetSizeLimit = this.maxAssetSize;
  19. const hints = this.hints;
  20. const assetFilter = this.assetFilter || (asset => !(/\.map$/.test(asset)));
  21. compiler.plugin("after-emit", (compilation, callback) => {
  22. const warnings = [];
  23. const getEntrypointSize = entrypoint =>
  24. entrypoint.getFiles()
  25. .filter(assetFilter)
  26. .map(file => compilation.assets[file])
  27. .filter(Boolean)
  28. .map(asset => asset.size())
  29. .reduce((currentSize, nextSize) => currentSize + nextSize, 0);
  30. const assetsOverSizeLimit = [];
  31. Object.keys(compilation.assets)
  32. .filter(assetFilter)
  33. .forEach(assetName => {
  34. const asset = compilation.assets[assetName];
  35. const size = asset.size();
  36. if(size > assetSizeLimit) {
  37. assetsOverSizeLimit.push({
  38. name: assetName,
  39. size: size,
  40. });
  41. asset.isOverSizeLimit = true;
  42. }
  43. });
  44. const entrypointsOverLimit = [];
  45. Object.keys(compilation.entrypoints)
  46. .forEach(key => {
  47. const entry = compilation.entrypoints[key];
  48. const size = getEntrypointSize(entry, compilation);
  49. if(size > entrypointSizeLimit) {
  50. entrypointsOverLimit.push({
  51. name: key,
  52. size: size,
  53. files: entry.getFiles().filter(assetFilter)
  54. });
  55. entry.isOverSizeLimit = true;
  56. }
  57. });
  58. if(hints) {
  59. // 1. Individual Chunk: Size < 250kb
  60. // 2. Collective Initial Chunks [entrypoint] (Each Set?): Size < 250kb
  61. // 3. No Async Chunks
  62. // if !1, then 2, if !2 return
  63. if(assetsOverSizeLimit.length > 0) {
  64. warnings.push(
  65. new AssetsOverSizeLimitWarning(
  66. assetsOverSizeLimit,
  67. assetSizeLimit));
  68. }
  69. if(entrypointsOverLimit.length > 0) {
  70. warnings.push(
  71. new EntrypointsOverSizeLimitWarning(
  72. entrypointsOverLimit,
  73. entrypointSizeLimit));
  74. }
  75. if(warnings.length > 0) {
  76. const hasAsyncChunks = compilation.chunks.filter(chunk => !chunk.isInitial()).length > 0;
  77. if(!hasAsyncChunks) {
  78. warnings.push(new NoAsyncChunksWarning());
  79. }
  80. if(hints === "error") {
  81. Array.prototype.push.apply(compilation.errors, warnings);
  82. } else {
  83. Array.prototype.push.apply(compilation.warnings, warnings);
  84. }
  85. }
  86. }
  87. callback();
  88. });
  89. }
  90. };