ExternalsPlugin.js 2.3 KB

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