You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

192 lines
5.8 KiB

4 years ago
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const Template = require("../Template");
  7. class WebWorkerMainTemplatePlugin {
  8. apply(mainTemplate) {
  9. const needChunkOnDemandLoadingCode = chunk => {
  10. for (const chunkGroup of chunk.groupsIterable) {
  11. if (chunkGroup.getNumberOfChildren() > 0) return true;
  12. }
  13. return false;
  14. };
  15. mainTemplate.hooks.localVars.tap(
  16. "WebWorkerMainTemplatePlugin",
  17. (source, chunk) => {
  18. if (needChunkOnDemandLoadingCode(chunk)) {
  19. return Template.asString([
  20. source,
  21. "",
  22. "// object to store loaded chunks",
  23. '// "1" means "already loaded"',
  24. "var installedChunks = {",
  25. Template.indent(
  26. chunk.ids.map(id => `${JSON.stringify(id)}: 1`).join(",\n")
  27. ),
  28. "};"
  29. ]);
  30. }
  31. return source;
  32. }
  33. );
  34. mainTemplate.hooks.requireEnsure.tap(
  35. "WebWorkerMainTemplatePlugin",
  36. (_, chunk, hash) => {
  37. const chunkFilename = mainTemplate.outputOptions.chunkFilename;
  38. const chunkMaps = chunk.getChunkMaps();
  39. return Template.asString([
  40. "promises.push(Promise.resolve().then(function() {",
  41. Template.indent([
  42. '// "1" is the signal for "already loaded"',
  43. "if(!installedChunks[chunkId]) {",
  44. Template.indent([
  45. "importScripts(" +
  46. "__webpack_require__.p + " +
  47. mainTemplate.getAssetPath(JSON.stringify(chunkFilename), {
  48. hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`,
  49. hashWithLength: length =>
  50. `" + ${mainTemplate.renderCurrentHashCode(
  51. hash,
  52. length
  53. )} + "`,
  54. chunk: {
  55. id: '" + chunkId + "',
  56. hash: `" + ${JSON.stringify(chunkMaps.hash)}[chunkId] + "`,
  57. hashWithLength(length) {
  58. const shortChunkHashMap = Object.create(null);
  59. for (const chunkId of Object.keys(chunkMaps.hash)) {
  60. if (typeof chunkMaps.hash[chunkId] === "string") {
  61. shortChunkHashMap[chunkId] = chunkMaps.hash[
  62. chunkId
  63. ].substr(0, length);
  64. }
  65. }
  66. return `" + ${JSON.stringify(
  67. shortChunkHashMap
  68. )}[chunkId] + "`;
  69. },
  70. contentHash: {
  71. javascript: `" + ${JSON.stringify(
  72. chunkMaps.contentHash.javascript
  73. )}[chunkId] + "`
  74. },
  75. contentHashWithLength: {
  76. javascript: length => {
  77. const shortContentHashMap = {};
  78. const contentHash = chunkMaps.contentHash.javascript;
  79. for (const chunkId of Object.keys(contentHash)) {
  80. if (typeof contentHash[chunkId] === "string") {
  81. shortContentHashMap[chunkId] = contentHash[
  82. chunkId
  83. ].substr(0, length);
  84. }
  85. }
  86. return `" + ${JSON.stringify(
  87. shortContentHashMap
  88. )}[chunkId] + "`;
  89. }
  90. },
  91. name: `" + (${JSON.stringify(
  92. chunkMaps.name
  93. )}[chunkId]||chunkId) + "`
  94. },
  95. contentHashType: "javascript"
  96. }) +
  97. ");"
  98. ]),
  99. "}"
  100. ]),
  101. "}));"
  102. ]);
  103. }
  104. );
  105. mainTemplate.hooks.bootstrap.tap(
  106. "WebWorkerMainTemplatePlugin",
  107. (source, chunk, hash) => {
  108. if (needChunkOnDemandLoadingCode(chunk)) {
  109. const chunkCallbackName =
  110. mainTemplate.outputOptions.chunkCallbackName;
  111. const globalObject = mainTemplate.outputOptions.globalObject;
  112. return Template.asString([
  113. source,
  114. `${globalObject}[${JSON.stringify(
  115. chunkCallbackName
  116. )}] = function webpackChunkCallback(chunkIds, moreModules) {`,
  117. Template.indent([
  118. "for(var moduleId in moreModules) {",
  119. Template.indent(
  120. mainTemplate.renderAddModule(
  121. hash,
  122. chunk,
  123. "moduleId",
  124. "moreModules[moduleId]"
  125. )
  126. ),
  127. "}",
  128. "while(chunkIds.length)",
  129. Template.indent("installedChunks[chunkIds.pop()] = 1;")
  130. ]),
  131. "};"
  132. ]);
  133. }
  134. return source;
  135. }
  136. );
  137. mainTemplate.hooks.hotBootstrap.tap(
  138. "WebWorkerMainTemplatePlugin",
  139. (source, chunk, hash) => {
  140. const hotUpdateChunkFilename =
  141. mainTemplate.outputOptions.hotUpdateChunkFilename;
  142. const hotUpdateMainFilename =
  143. mainTemplate.outputOptions.hotUpdateMainFilename;
  144. const hotUpdateFunction = mainTemplate.outputOptions.hotUpdateFunction;
  145. const globalObject = mainTemplate.outputOptions.globalObject;
  146. const currentHotUpdateChunkFilename = mainTemplate.getAssetPath(
  147. JSON.stringify(hotUpdateChunkFilename),
  148. {
  149. hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`,
  150. hashWithLength: length =>
  151. `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`,
  152. chunk: {
  153. id: '" + chunkId + "'
  154. }
  155. }
  156. );
  157. const currentHotUpdateMainFilename = mainTemplate.getAssetPath(
  158. JSON.stringify(hotUpdateMainFilename),
  159. {
  160. hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`,
  161. hashWithLength: length =>
  162. `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`
  163. }
  164. );
  165. return (
  166. source +
  167. "\n" +
  168. `var parentHotUpdateCallback = ${globalObject}[${JSON.stringify(
  169. hotUpdateFunction
  170. )}];\n` +
  171. `${globalObject}[${JSON.stringify(hotUpdateFunction)}] = ` +
  172. Template.getFunctionContent(
  173. require("./WebWorkerMainTemplate.runtime")
  174. )
  175. .replace(/\/\/\$semicolon/g, ";")
  176. .replace(/\$require\$/g, mainTemplate.requireFn)
  177. .replace(/\$hotMainFilename\$/g, currentHotUpdateMainFilename)
  178. .replace(/\$hotChunkFilename\$/g, currentHotUpdateChunkFilename)
  179. .replace(/\$hash\$/g, JSON.stringify(hash))
  180. );
  181. }
  182. );
  183. mainTemplate.hooks.hash.tap("WebWorkerMainTemplatePlugin", hash => {
  184. hash.update("webworker");
  185. hash.update("4");
  186. });
  187. }
  188. }
  189. module.exports = WebWorkerMainTemplatePlugin;