ExternalsPlugin.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const { ModuleExternalInitFragment } = require("./ExternalModule");
  7. const ExternalModuleFactoryPlugin = require("./ExternalModuleFactoryPlugin");
  8. const ConcatenatedModule = require("./optimize/ConcatenatedModule");
  9. /**
  10. * @import {
  11. * ExternalsType,
  12. * Externals
  13. * } from "../declarations/WebpackOptions"
  14. */
  15. /** @import Compiler from "./Compiler" */
  16. /** @import { Imported } from "./ExternalModule" */
  17. /** @import Dependency from "./Dependency" */
  18. const PLUGIN_NAME = "ExternalsPlugin";
  19. class ExternalsPlugin {
  20. /**
  21. * Creates an instance of ExternalsPlugin.
  22. * @param {ExternalsType | ((dependency: Dependency) => ExternalsType)} type default external type
  23. * @param {Externals} externals externals config
  24. */
  25. constructor(type, externals) {
  26. this.type = type;
  27. /** @type {Externals} */
  28. this.externals = externals;
  29. }
  30. /**
  31. * Applies the plugin by registering its hooks on the compiler.
  32. * @param {Compiler} compiler the compiler instance
  33. * @returns {void}
  34. */
  35. apply(compiler) {
  36. compiler.hooks.compile.tap(PLUGIN_NAME, ({ normalModuleFactory }) => {
  37. new ExternalModuleFactoryPlugin(this.type, this.externals).apply(
  38. normalModuleFactory
  39. );
  40. });
  41. compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
  42. const { concatenatedModuleInfo } =
  43. ConcatenatedModule.getCompilationHooks(compilation);
  44. concatenatedModuleInfo.tap(PLUGIN_NAME, (updatedInfo, moduleInfo) => {
  45. const rawExportMap = updatedInfo.rawExportMap;
  46. if (!rawExportMap) {
  47. return;
  48. }
  49. const chunkInitFragments = moduleInfo.chunkInitFragments;
  50. const moduleExternalInitFragments =
  51. /** @type {InstanceType<ModuleExternalInitFragment>[]} */
  52. (
  53. chunkInitFragments
  54. ? /** @type {unknown[]} */
  55. (chunkInitFragments).filter(
  56. (fragment) => fragment instanceof ModuleExternalInitFragment
  57. )
  58. : []
  59. );
  60. let initFragmentChanged = false;
  61. for (const fragment of moduleExternalInitFragments) {
  62. const imported = fragment.getImported();
  63. if (Array.isArray(imported)) {
  64. const newImported =
  65. /** @type {Imported} */
  66. (
  67. imported.map(([specifier, finalName]) => [
  68. specifier,
  69. rawExportMap.has(specifier)
  70. ? rawExportMap.get(specifier)
  71. : finalName
  72. ])
  73. );
  74. fragment.setImported(newImported);
  75. initFragmentChanged = true;
  76. }
  77. }
  78. if (initFragmentChanged) {
  79. return true;
  80. }
  81. });
  82. });
  83. }
  84. }
  85. module.exports = ExternalsPlugin;