WebWorkerMainTemplatePlugin.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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. mainTemplate.getAssetPath(JSON.stringify(chunkFilename), {
  47. hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`,
  48. hashWithLength: length =>
  49. `" + ${mainTemplate.renderCurrentHashCode(
  50. hash,
  51. length
  52. )} + "`,
  53. chunk: {
  54. id: '" + chunkId + "',
  55. hash: `" + ${JSON.stringify(chunkMaps.hash)}[chunkId] + "`,
  56. hashWithLength(length) {
  57. const shortChunkHashMap = Object.create(null);
  58. for (const chunkId of Object.keys(chunkMaps.hash)) {
  59. if (typeof chunkMaps.hash[chunkId] === "string") {
  60. shortChunkHashMap[chunkId] = chunkMaps.hash[
  61. chunkId
  62. ].substr(0, length);
  63. }
  64. }
  65. return `" + ${JSON.stringify(
  66. shortChunkHashMap
  67. )}[chunkId] + "`;
  68. },
  69. contentHash: {
  70. javascript: `" + ${JSON.stringify(
  71. chunkMaps.contentHash.javascript
  72. )}[chunkId] + "`
  73. },
  74. contentHashWithLength: {
  75. javascript: length => {
  76. const shortContentHashMap = {};
  77. const contentHash = chunkMaps.contentHash.javascript;
  78. for (const chunkId of Object.keys(contentHash)) {
  79. if (typeof contentHash[chunkId] === "string") {
  80. shortContentHashMap[chunkId] = contentHash[
  81. chunkId
  82. ].substr(0, length);
  83. }
  84. }
  85. return `" + ${JSON.stringify(
  86. shortContentHashMap
  87. )}[chunkId] + "`;
  88. }
  89. },
  90. name: `" + (${JSON.stringify(
  91. chunkMaps.name
  92. )}[chunkId]||chunkId) + "`
  93. },
  94. contentHashType: "javascript"
  95. }) +
  96. ");"
  97. ]),
  98. "}"
  99. ]),
  100. "}));"
  101. ]);
  102. }
  103. );
  104. mainTemplate.hooks.bootstrap.tap(
  105. "WebWorkerMainTemplatePlugin",
  106. (source, chunk, hash) => {
  107. if (needChunkOnDemandLoadingCode(chunk)) {
  108. const chunkCallbackName =
  109. mainTemplate.outputOptions.chunkCallbackName;
  110. const globalObject = mainTemplate.outputOptions.globalObject;
  111. return Template.asString([
  112. source,
  113. `${globalObject}[${JSON.stringify(
  114. chunkCallbackName
  115. )}] = function webpackChunkCallback(chunkIds, moreModules) {`,
  116. Template.indent([
  117. "for(var moduleId in moreModules) {",
  118. Template.indent(
  119. mainTemplate.renderAddModule(
  120. hash,
  121. chunk,
  122. "moduleId",
  123. "moreModules[moduleId]"
  124. )
  125. ),
  126. "}",
  127. "while(chunkIds.length)",
  128. Template.indent("installedChunks[chunkIds.pop()] = 1;")
  129. ]),
  130. "};"
  131. ]);
  132. }
  133. return source;
  134. }
  135. );
  136. mainTemplate.hooks.hotBootstrap.tap(
  137. "WebWorkerMainTemplatePlugin",
  138. (source, chunk, hash) => {
  139. const hotUpdateChunkFilename =
  140. mainTemplate.outputOptions.hotUpdateChunkFilename;
  141. const hotUpdateMainFilename =
  142. mainTemplate.outputOptions.hotUpdateMainFilename;
  143. const hotUpdateFunction = mainTemplate.outputOptions.hotUpdateFunction;
  144. const globalObject = mainTemplate.outputOptions.globalObject;
  145. const currentHotUpdateChunkFilename = mainTemplate.getAssetPath(
  146. JSON.stringify(hotUpdateChunkFilename),
  147. {
  148. hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`,
  149. hashWithLength: length =>
  150. `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`,
  151. chunk: {
  152. id: '" + chunkId + "'
  153. }
  154. }
  155. );
  156. const currentHotUpdateMainFilename = mainTemplate.getAssetPath(
  157. JSON.stringify(hotUpdateMainFilename),
  158. {
  159. hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`,
  160. hashWithLength: length =>
  161. `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`
  162. }
  163. );
  164. return (
  165. source +
  166. "\n" +
  167. `var parentHotUpdateCallback = ${globalObject}[${JSON.stringify(
  168. hotUpdateFunction
  169. )}];\n` +
  170. `${globalObject}[${JSON.stringify(hotUpdateFunction)}] = ` +
  171. Template.getFunctionContent(
  172. require("./WebWorkerMainTemplate.runtime")
  173. )
  174. .replace(/\/\/\$semicolon/g, ";")
  175. .replace(/\$require\$/g, mainTemplate.requireFn)
  176. .replace(/\$hotMainFilename\$/g, currentHotUpdateMainFilename)
  177. .replace(/\$hotChunkFilename\$/g, currentHotUpdateChunkFilename)
  178. .replace(/\$hash\$/g, JSON.stringify(hash))
  179. );
  180. }
  181. );
  182. mainTemplate.hooks.hash.tap("WebWorkerMainTemplatePlugin", hash => {
  183. hash.update("webworker");
  184. hash.update("4");
  185. });
  186. }
  187. }
  188. module.exports = WebWorkerMainTemplatePlugin;