SystemMainTemplatePlugin.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  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.getModules().filter(m => m.external);
  28. // The name this bundle should be registered as with System
  29. const name = this.name
  30. ? `${JSON.stringify(
  31. mainTemplate.getAssetPath(this.name, { hash, chunk })
  32. )}, `
  33. : "";
  34. // The array of dependencies that are external to webpack and will be provided by System
  35. const systemDependencies = JSON.stringify(
  36. externals.map(m =>
  37. typeof m.request === "object" ? m.request.amd : m.request
  38. )
  39. );
  40. // The name of the variable provided by System for exporting
  41. const dynamicExport = "__WEBPACK_DYNAMIC_EXPORT__";
  42. // An array of the internal variable names for the webpack externals
  43. const externalWebpackNames = externals.map(
  44. m => `__WEBPACK_EXTERNAL_MODULE_${Template.toIdentifier(`${m.id}`)}__`
  45. );
  46. // Declaring variables for the internal variable names for the webpack externals
  47. const externalVarDeclarations =
  48. externalWebpackNames.length > 0
  49. ? `var ${externalWebpackNames.join(", ")};`
  50. : "";
  51. // The system.register format requires an array of setter functions for externals.
  52. const setters =
  53. externalWebpackNames.length === 0
  54. ? ""
  55. : Template.asString([
  56. "setters: [",
  57. Template.indent(
  58. externalWebpackNames
  59. .map(external =>
  60. Template.asString([
  61. "function(module) {",
  62. Template.indent(`${external} = module;`),
  63. "}"
  64. ])
  65. )
  66. .join(",\n")
  67. ),
  68. "],"
  69. ]);
  70. return new ConcatSource(
  71. Template.asString([
  72. `System.register(${name}${systemDependencies}, function(${dynamicExport}) {`,
  73. Template.indent([
  74. externalVarDeclarations,
  75. "return {",
  76. Template.indent([
  77. setters,
  78. "execute: function() {",
  79. Template.indent(`${dynamicExport}(`)
  80. ])
  81. ])
  82. ]) + "\n",
  83. source,
  84. "\n" +
  85. Template.asString([
  86. Template.indent([
  87. Template.indent([Template.indent([");"]), "}"]),
  88. "};"
  89. ]),
  90. "})"
  91. ])
  92. );
  93. };
  94. for (const template of [mainTemplate, chunkTemplate]) {
  95. template.hooks.renderWithEntry.tap(
  96. "SystemMainTemplatePlugin",
  97. onRenderWithEntry
  98. );
  99. }
  100. mainTemplate.hooks.globalHashPaths.tap(
  101. "SystemMainTemplatePlugin",
  102. paths => {
  103. if (this.name) {
  104. paths.push(this.name);
  105. }
  106. return paths;
  107. }
  108. );
  109. mainTemplate.hooks.hash.tap("SystemMainTemplatePlugin", hash => {
  110. hash.update("exports system");
  111. if (this.name) {
  112. hash.update(this.name);
  113. }
  114. });
  115. }
  116. }
  117. module.exports = SystemMainTemplatePlugin;