ContainerPlugin.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra, Zackary Jackson @ScriptedAlchemy, Marais Rossouw @maraisr
  4. */
  5. "use strict";
  6. const memoize = require("../util/memoize");
  7. const ContainerEntryDependency = require("./ContainerEntryDependency");
  8. const ContainerEntryModuleFactory = require("./ContainerEntryModuleFactory");
  9. const ContainerExposedDependency = require("./ContainerExposedDependency");
  10. const { parseOptions } = require("./options");
  11. /** @typedef {import("../../declarations/plugins/container/ContainerPlugin").ContainerPluginOptions} ContainerPluginOptions */
  12. /** @typedef {import("../Compiler")} Compiler */
  13. /** @typedef {import("./ContainerEntryModule").ExposesList} ExposesList */
  14. const getModuleFederationPlugin = memoize(() =>
  15. require("./ModuleFederationPlugin")
  16. );
  17. const PLUGIN_NAME = "ContainerPlugin";
  18. class ContainerPlugin {
  19. /**
  20. * Creates an instance of ContainerPlugin.
  21. * @param {ContainerPluginOptions} options options
  22. */
  23. constructor(options) {
  24. /** @type {ContainerPluginOptions} */
  25. this.options = options;
  26. }
  27. /**
  28. * Applies the plugin by registering its hooks on the compiler.
  29. * @param {Compiler} compiler the compiler instance
  30. * @returns {void}
  31. */
  32. apply(compiler) {
  33. compiler.hooks.validate.tap(PLUGIN_NAME, () => {
  34. compiler.validate(
  35. () => require("../../schemas/plugins/container/ContainerPlugin.json"),
  36. this.options,
  37. {
  38. name: "Container Plugin",
  39. baseDataPath: "options"
  40. },
  41. (options) =>
  42. require("../../schemas/plugins/container/ContainerPlugin.check")(
  43. options
  44. )
  45. );
  46. });
  47. const library = this.options.library || {
  48. type: "var",
  49. name: this.options.name
  50. };
  51. if (!compiler.options.output.enabledLibraryTypes.includes(library.type)) {
  52. compiler.options.output.enabledLibraryTypes.push(library.type);
  53. }
  54. const exposes = /** @type {ExposesList} */ (
  55. parseOptions(
  56. this.options.exposes,
  57. (item) => ({
  58. import: Array.isArray(item) ? item : [item],
  59. name: undefined
  60. }),
  61. (item) => ({
  62. import: Array.isArray(item.import) ? item.import : [item.import],
  63. name: item.name || undefined
  64. })
  65. )
  66. );
  67. const shareScope = this.options.shareScope || "default";
  68. compiler.hooks.make.tapAsync(PLUGIN_NAME, (compilation, callback) => {
  69. const hooks =
  70. getModuleFederationPlugin().getCompilationHooks(compilation);
  71. const dep = new ContainerEntryDependency(
  72. this.options.name,
  73. exposes,
  74. shareScope
  75. );
  76. dep.loc = { name: this.options.name };
  77. compilation.addEntry(
  78. compilation.options.context,
  79. dep,
  80. {
  81. name: this.options.name,
  82. filename: this.options.filename,
  83. runtime: this.options.runtime,
  84. library
  85. },
  86. (error) => {
  87. if (error) return callback(error);
  88. hooks.addContainerEntryDependency.call(dep);
  89. callback();
  90. }
  91. );
  92. });
  93. compiler.hooks.thisCompilation.tap(
  94. PLUGIN_NAME,
  95. (compilation, { normalModuleFactory }) => {
  96. compilation.dependencyFactories.set(
  97. ContainerEntryDependency,
  98. new ContainerEntryModuleFactory()
  99. );
  100. compilation.dependencyFactories.set(
  101. ContainerExposedDependency,
  102. normalModuleFactory
  103. );
  104. }
  105. );
  106. }
  107. }
  108. module.exports = ContainerPlugin;