StartupChunkDependenciesPlugin.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. */
  4. "use strict";
  5. const RuntimeGlobals = require("../RuntimeGlobals");
  6. const StartupChunkDependenciesRuntimeModule = require("./StartupChunkDependenciesRuntimeModule");
  7. const StartupEntrypointRuntimeModule = require("./StartupEntrypointRuntimeModule");
  8. /** @typedef {import("../../declarations/WebpackOptions").ChunkLoadingType} ChunkLoadingType */
  9. /** @typedef {import("../Chunk")} Chunk */
  10. /** @typedef {import("../Compiler")} Compiler */
  11. /**
  12. * Options that describe which chunk loading backend should receive startup
  13. * dependency handling and whether the runtime should wait for those chunks
  14. * asynchronously.
  15. * @typedef {object} Options
  16. * @property {ChunkLoadingType} chunkLoading
  17. * @property {boolean=} asyncChunkLoading
  18. */
  19. const PLUGIN_NAME = "StartupChunkDependenciesPlugin";
  20. /**
  21. * Adds runtime modules that delay entry startup until entry-dependent chunks
  22. * required by the selected chunk loading strategy have been loaded.
  23. */
  24. class StartupChunkDependenciesPlugin {
  25. /**
  26. * Configures which chunk loading implementation this plugin should enhance
  27. * and whether startup waits should use promises or synchronous ensures.
  28. * @param {Options} options options
  29. */
  30. constructor(options) {
  31. /** @type {ChunkLoadingType} */
  32. this.chunkLoading = options.chunkLoading;
  33. /** @type {boolean} */
  34. this.asyncChunkLoading =
  35. typeof options.asyncChunkLoading === "boolean"
  36. ? options.asyncChunkLoading
  37. : true;
  38. }
  39. /**
  40. * Registers compilation hooks that attach the startup dependency runtime
  41. * modules to entry chunks using the configured chunk loading mechanism.
  42. * @param {Compiler} compiler the compiler instance
  43. * @returns {void}
  44. */
  45. apply(compiler) {
  46. compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
  47. const globalChunkLoading = compilation.outputOptions.chunkLoading;
  48. /**
  49. * Determines whether a chunk uses the chunk loading backend that this
  50. * plugin is responsible for augmenting.
  51. * @param {Chunk} chunk chunk to check
  52. * @returns {boolean} true, when the plugin is enabled for the chunk
  53. */
  54. const isEnabledForChunk = (chunk) => {
  55. const options = chunk.getEntryOptions();
  56. const chunkLoading =
  57. options && options.chunkLoading !== undefined
  58. ? options.chunkLoading
  59. : globalChunkLoading;
  60. return chunkLoading === this.chunkLoading;
  61. };
  62. compilation.hooks.additionalTreeRuntimeRequirements.tap(
  63. PLUGIN_NAME,
  64. (chunk, set, { chunkGraph }) => {
  65. if (!isEnabledForChunk(chunk)) return;
  66. if (chunkGraph.hasChunkEntryDependentChunks(chunk)) {
  67. set.add(RuntimeGlobals.startup);
  68. set.add(RuntimeGlobals.ensureChunk);
  69. set.add(RuntimeGlobals.ensureChunkIncludeEntries);
  70. compilation.addRuntimeModule(
  71. chunk,
  72. new StartupChunkDependenciesRuntimeModule(this.asyncChunkLoading)
  73. );
  74. }
  75. }
  76. );
  77. compilation.hooks.runtimeRequirementInTree
  78. .for(RuntimeGlobals.startupEntrypoint)
  79. .tap(PLUGIN_NAME, (chunk, set) => {
  80. if (!isEnabledForChunk(chunk)) return;
  81. set.add(RuntimeGlobals.require);
  82. set.add(RuntimeGlobals.ensureChunk);
  83. set.add(RuntimeGlobals.ensureChunkIncludeEntries);
  84. compilation.addRuntimeModule(
  85. chunk,
  86. new StartupEntrypointRuntimeModule(this.asyncChunkLoading)
  87. );
  88. });
  89. });
  90. }
  91. }
  92. module.exports = StartupChunkDependenciesPlugin;