10
0

ContainerPlugin.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  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 createSchemaValidation = require("../util/create-schema-validation");
  7. const memoize = require("../util/memoize");
  8. const ContainerEntryDependency = require("./ContainerEntryDependency");
  9. const ContainerEntryModuleFactory = require("./ContainerEntryModuleFactory");
  10. const ContainerExposedDependency = require("./ContainerExposedDependency");
  11. const { parseOptions } = require("./options");
  12. /** @typedef {import("../../declarations/plugins/container/ContainerPlugin").ContainerPluginOptions} ContainerPluginOptions */
  13. /** @typedef {import("../Compiler")} Compiler */
  14. /** @typedef {import("./ContainerEntryModule").ExposeOptions} ExposeOptions */
  15. /** @typedef {import("./ContainerEntryModule").ExposesList} ExposesList */
  16. const getModuleFederationPlugin = memoize(() =>
  17. require("./ModuleFederationPlugin")
  18. );
  19. const validate = createSchemaValidation(
  20. require("../../schemas/plugins/container/ContainerPlugin.check.js"),
  21. () => require("../../schemas/plugins/container/ContainerPlugin.json"),
  22. {
  23. name: "Container Plugin",
  24. baseDataPath: "options"
  25. }
  26. );
  27. const PLUGIN_NAME = "ContainerPlugin";
  28. class ContainerPlugin {
  29. /**
  30. * @param {ContainerPluginOptions} options options
  31. */
  32. constructor(options) {
  33. validate(options);
  34. this._options = {
  35. name: options.name,
  36. shareScope: options.shareScope || "default",
  37. library: options.library || {
  38. type: "var",
  39. name: options.name
  40. },
  41. runtime: options.runtime,
  42. filename: options.filename || undefined,
  43. exposes: /** @type {ExposesList} */ (
  44. parseOptions(
  45. options.exposes,
  46. item => ({
  47. import: Array.isArray(item) ? item : [item],
  48. name: undefined
  49. }),
  50. item => ({
  51. import: Array.isArray(item.import) ? item.import : [item.import],
  52. name: item.name || undefined
  53. })
  54. )
  55. )
  56. };
  57. }
  58. /**
  59. * Apply the plugin
  60. * @param {Compiler} compiler the compiler instance
  61. * @returns {void}
  62. */
  63. apply(compiler) {
  64. const { name, exposes, shareScope, filename, library, runtime } =
  65. this._options;
  66. if (!compiler.options.output.enabledLibraryTypes.includes(library.type)) {
  67. compiler.options.output.enabledLibraryTypes.push(library.type);
  68. }
  69. compiler.hooks.make.tapAsync(PLUGIN_NAME, (compilation, callback) => {
  70. const hooks =
  71. getModuleFederationPlugin().getCompilationHooks(compilation);
  72. const dep = new ContainerEntryDependency(name, exposes, shareScope);
  73. dep.loc = { name };
  74. compilation.addEntry(
  75. /** @type {string} */ (compilation.options.context),
  76. dep,
  77. {
  78. name,
  79. filename,
  80. runtime,
  81. library
  82. },
  83. error => {
  84. if (error) return callback(error);
  85. hooks.addContainerEntryDependency.call(dep);
  86. callback();
  87. }
  88. );
  89. });
  90. compiler.hooks.thisCompilation.tap(
  91. PLUGIN_NAME,
  92. (compilation, { normalModuleFactory }) => {
  93. compilation.dependencyFactories.set(
  94. ContainerEntryDependency,
  95. new ContainerEntryModuleFactory()
  96. );
  97. compilation.dependencyFactories.set(
  98. ContainerExposedDependency,
  99. normalModuleFactory
  100. );
  101. }
  102. );
  103. }
  104. }
  105. module.exports = ContainerPlugin;