ExternalsPlugin.js 2.5 KB

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