ExternalsPlugin.js 2.6 KB

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