SystemMainTemplatePlugin.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Joel Denning @joeldenning
  4. */
  5. "use strict";
  6. const { ConcatSource } = require("webpack-sources");
  7. const Template = require("./Template");
  8. /** @typedef {import("./Compilation")} Compilation */
  9. /**
  10. * @typedef {Object} SystemMainTemplatePluginOptions
  11. * @param {string=} name the library name
  12. */
  13. class SystemMainTemplatePlugin {
  14. /**
  15. * @param {SystemMainTemplatePluginOptions} options the plugin options
  16. */
  17. constructor(options) {
  18. this.name = options.name;
  19. }
  20. /**
  21. * @param {Compilation} compilation the compilation instance
  22. * @returns {void}
  23. */
  24. apply(compilation) {
  25. const { mainTemplate, chunkTemplate } = compilation;
  26. const onRenderWithEntry = (source, chunk, hash) => {
  27. const externals = chunk
  28. .getModules()
  29. .filter(m => m.external && m.externalType === "system");
  30. // The name this bundle should be registered as with System
  31. const name = this.name
  32. ? `${JSON.stringify(
  33. mainTemplate.getAssetPath(this.name, { hash, chunk })
  34. )}, `
  35. : "";
  36. // The array of dependencies that are external to webpack and will be provided by System
  37. const systemDependencies = JSON.stringify(
  38. externals.map(m =>
  39. typeof m.request === "object" ? m.request.amd : m.request
  40. )
  41. );
  42. // The name of the variable provided by System for exporting
  43. const dynamicExport = "__WEBPACK_DYNAMIC_EXPORT__";
  44. // An array of the internal variable names for the webpack externals
  45. const externalWebpackNames = externals.map(
  46. m => `__WEBPACK_EXTERNAL_MODULE_${Template.toIdentifier(`${m.id}`)}__`
  47. );
  48. // Declaring variables for the internal variable names for the webpack externals
  49. const externalVarDeclarations =
  50. externalWebpackNames.length > 0
  51. ? `var ${externalWebpackNames.join(", ")};`
  52. : "";
  53. // The system.register format requires an array of setter functions for externals.
  54. const setters =
  55. externalWebpackNames.length === 0
  56. ? ""
  57. : Template.asString([
  58. "setters: [",
  59. Template.indent(
  60. externalWebpackNames
  61. .map(external =>
  62. Template.asString([
  63. "function(module) {",
  64. Template.indent(`${external} = module;`),
  65. "}"
  66. ])
  67. )
  68. .join(",\n")
  69. ),
  70. "],"
  71. ]);
  72. return new ConcatSource(
  73. Template.asString([
  74. `System.register(${name}${systemDependencies}, function(${dynamicExport}) {`,
  75. Template.indent([
  76. externalVarDeclarations,
  77. "return {",
  78. Template.indent([
  79. setters,
  80. "execute: function() {",
  81. Template.indent(`${dynamicExport}(`)
  82. ])
  83. ])
  84. ]) + "\n",
  85. source,
  86. "\n" +
  87. Template.asString([
  88. Template.indent([
  89. Template.indent([Template.indent([");"]), "}"]),
  90. "};"
  91. ]),
  92. "})"
  93. ])
  94. );
  95. };
  96. for (const template of [mainTemplate, chunkTemplate]) {
  97. template.hooks.renderWithEntry.tap(
  98. "SystemMainTemplatePlugin",
  99. onRenderWithEntry
  100. );
  101. }
  102. mainTemplate.hooks.globalHashPaths.tap(
  103. "SystemMainTemplatePlugin",
  104. paths => {
  105. if (this.name) {
  106. paths.push(this.name);
  107. }
  108. return paths;
  109. }
  110. );
  111. mainTemplate.hooks.hash.tap("SystemMainTemplatePlugin", hash => {
  112. hash.update("exports system");
  113. if (this.name) {
  114. hash.update(this.name);
  115. }
  116. });
  117. }
  118. }
  119. module.exports = SystemMainTemplatePlugin;