ModuleChunkLoadingPlugin.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const RuntimeGlobals = require("../RuntimeGlobals");
  7. const ExportWebpackRequireRuntimeModule = require("./ExportWebpackRequireRuntimeModule");
  8. const ModuleChunkLoadingRuntimeModule = require("./ModuleChunkLoadingRuntimeModule");
  9. /** @typedef {import("../Chunk")} Chunk */
  10. /** @typedef {import("../Compiler")} Compiler */
  11. /** @typedef {import("../Module").RuntimeRequirements} RuntimeRequirements */
  12. const PLUGIN_NAME = "ModuleChunkLoadingPlugin";
  13. class ModuleChunkLoadingPlugin {
  14. /**
  15. * Apply the plugin
  16. * @param {Compiler} compiler the compiler instance
  17. * @returns {void}
  18. */
  19. apply(compiler) {
  20. compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
  21. const globalChunkLoading = compilation.outputOptions.chunkLoading;
  22. /**
  23. * @param {Chunk} chunk chunk to check
  24. * @returns {boolean} true, when the plugin is enabled for the chunk
  25. */
  26. const isEnabledForChunk = (chunk) => {
  27. const options = chunk.getEntryOptions();
  28. const chunkLoading =
  29. options && options.chunkLoading !== undefined
  30. ? options.chunkLoading
  31. : globalChunkLoading;
  32. return chunkLoading === "import";
  33. };
  34. /** @type {WeakSet<Chunk>} */
  35. const onceForChunkSet = new WeakSet();
  36. /**
  37. * @param {Chunk} chunk chunk to check
  38. * @param {RuntimeRequirements} set runtime requirements
  39. */
  40. const handler = (chunk, set) => {
  41. if (onceForChunkSet.has(chunk)) return;
  42. onceForChunkSet.add(chunk);
  43. if (!isEnabledForChunk(chunk)) return;
  44. set.add(RuntimeGlobals.moduleFactoriesAddOnly);
  45. set.add(RuntimeGlobals.hasOwnProperty);
  46. compilation.addRuntimeModule(
  47. chunk,
  48. new ModuleChunkLoadingRuntimeModule(set)
  49. );
  50. };
  51. compilation.hooks.runtimeRequirementInTree
  52. .for(RuntimeGlobals.ensureChunkHandlers)
  53. .tap(PLUGIN_NAME, handler);
  54. compilation.hooks.runtimeRequirementInTree
  55. .for(RuntimeGlobals.baseURI)
  56. .tap(PLUGIN_NAME, handler);
  57. compilation.hooks.runtimeRequirementInTree
  58. .for(RuntimeGlobals.externalInstallChunk)
  59. .tap(PLUGIN_NAME, handler);
  60. compilation.hooks.runtimeRequirementInTree
  61. .for(RuntimeGlobals.onChunksLoaded)
  62. .tap(PLUGIN_NAME, handler);
  63. compilation.hooks.runtimeRequirementInTree
  64. .for(RuntimeGlobals.hmrDownloadUpdateHandlers)
  65. .tap(PLUGIN_NAME, handler);
  66. compilation.hooks.runtimeRequirementInTree
  67. .for(RuntimeGlobals.hmrDownloadManifest)
  68. .tap(PLUGIN_NAME, handler);
  69. compilation.hooks.runtimeRequirementInTree
  70. .for(RuntimeGlobals.externalInstallChunk)
  71. .tap(PLUGIN_NAME, (chunk) => {
  72. if (!isEnabledForChunk(chunk)) return;
  73. compilation.addRuntimeModule(
  74. chunk,
  75. new ExportWebpackRequireRuntimeModule()
  76. );
  77. });
  78. // We need public path only when we prefetch/preload chunk or public path is not `auto`
  79. compilation.hooks.runtimeRequirementInTree
  80. .for(RuntimeGlobals.prefetchChunkHandlers)
  81. .tap(PLUGIN_NAME, (chunk, set) => {
  82. if (!isEnabledForChunk(chunk)) return;
  83. set.add(RuntimeGlobals.publicPath);
  84. });
  85. compilation.hooks.runtimeRequirementInTree
  86. .for(RuntimeGlobals.preloadChunkHandlers)
  87. .tap(PLUGIN_NAME, (chunk, set) => {
  88. if (!isEnabledForChunk(chunk)) return;
  89. set.add(RuntimeGlobals.publicPath);
  90. });
  91. compilation.hooks.runtimeRequirementInTree
  92. .for(RuntimeGlobals.ensureChunkHandlers)
  93. .tap(PLUGIN_NAME, (chunk, set) => {
  94. if (!isEnabledForChunk(chunk)) return;
  95. if (compilation.outputOptions.publicPath !== "auto") {
  96. set.add(RuntimeGlobals.publicPath);
  97. }
  98. set.add(RuntimeGlobals.getChunkScriptFilename);
  99. });
  100. compilation.hooks.runtimeRequirementInTree
  101. .for(RuntimeGlobals.hmrDownloadUpdateHandlers)
  102. .tap(PLUGIN_NAME, (chunk, set) => {
  103. if (!isEnabledForChunk(chunk)) return;
  104. set.add(RuntimeGlobals.publicPath);
  105. set.add(RuntimeGlobals.loadScript);
  106. set.add(RuntimeGlobals.getChunkUpdateScriptFilename);
  107. set.add(RuntimeGlobals.moduleCache);
  108. set.add(RuntimeGlobals.hmrModuleData);
  109. set.add(RuntimeGlobals.moduleFactoriesAddOnly);
  110. });
  111. compilation.hooks.runtimeRequirementInTree
  112. .for(RuntimeGlobals.hmrDownloadManifest)
  113. .tap(PLUGIN_NAME, (chunk, set) => {
  114. if (!isEnabledForChunk(chunk)) return;
  115. set.add(RuntimeGlobals.publicPath);
  116. set.add(RuntimeGlobals.getUpdateManifestFilename);
  117. });
  118. compilation.hooks.additionalTreeRuntimeRequirements.tap(
  119. PLUGIN_NAME,
  120. (chunk, set, { chunkGraph }) => {
  121. if (chunkGraph.hasChunkEntryDependentChunks(chunk)) {
  122. set.add(RuntimeGlobals.externalInstallChunk);
  123. }
  124. }
  125. );
  126. });
  127. }
  128. }
  129. module.exports = ModuleChunkLoadingPlugin;