NodeMainTemplatePlugin.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. var Template = require("../Template");
  6. function NodeMainTemplatePlugin(asyncChunkLoading) {
  7. this.asyncChunkLoading = asyncChunkLoading;
  8. }
  9. module.exports = NodeMainTemplatePlugin;
  10. NodeMainTemplatePlugin.prototype.apply = function(mainTemplate) {
  11. var self = this;
  12. mainTemplate.plugin("local-vars", function(source, chunk) {
  13. if(chunk.chunks.length > 0) {
  14. return this.asString([
  15. source,
  16. "",
  17. "// object to store loaded chunks",
  18. "// \"0\" means \"already loaded\"",
  19. "var installedChunks = {",
  20. this.indent(
  21. chunk.ids.map(function(id) {
  22. return id + ": 0";
  23. }).join(",\n")
  24. ),
  25. "};"
  26. ]);
  27. }
  28. return source;
  29. });
  30. mainTemplate.plugin("require-extensions", function(source, chunk) {
  31. if(chunk.chunks.length > 0) {
  32. return this.asString([
  33. source,
  34. "",
  35. "// uncatched error handler for webpack runtime",
  36. this.requireFn + ".oe = function(err) {",
  37. this.indent([
  38. "process.nextTick(function() {",
  39. this.indent("throw err; // catch this error by using System.import().catch()"),
  40. "});"
  41. ]),
  42. "};"
  43. ]);
  44. }
  45. return source;
  46. });
  47. mainTemplate.plugin("require-ensure", function(_, chunk, hash) {
  48. var chunkFilename = this.outputOptions.chunkFilename;
  49. var chunkMaps = chunk.getChunkMaps();
  50. var insertMoreModules = [
  51. "var moreModules = chunk.modules, chunkIds = chunk.ids;",
  52. "for(var moduleId in moreModules) {",
  53. this.indent(this.renderAddModule(hash, chunk, "moduleId", "moreModules[moduleId]")),
  54. "}"
  55. ];
  56. if(self.asyncChunkLoading) {
  57. return this.asString([
  58. "// \"0\" is the signal for \"already loaded\"",
  59. "if(installedChunks[chunkId] === 0)",
  60. this.indent([
  61. "return Promise.resolve();"
  62. ]),
  63. "// array of [resolve, reject, promise] means \"currently loading\"",
  64. "if(installedChunks[chunkId])",
  65. this.indent([
  66. "return installedChunks[chunkId][2];"
  67. ]),
  68. "// load the chunk and return promise to it",
  69. "var promise = new Promise(function(resolve, reject) {",
  70. this.indent([
  71. "installedChunks[chunkId] = [resolve, reject];",
  72. "var filename = __dirname + " + this.applyPluginsWaterfall("asset-path", JSON.stringify("/" + chunkFilename), {
  73. hash: "\" + " + this.renderCurrentHashCode(hash) + " + \"",
  74. hashWithLength: function(length) {
  75. return "\" + " + this.renderCurrentHashCode(hash, length) + " + \"";
  76. }.bind(this),
  77. chunk: {
  78. id: "\" + chunkId + \"",
  79. hash: "\" + " + JSON.stringify(chunkMaps.hash) + "[chunkId] + \"",
  80. hashWithLength: function(length) {
  81. var shortChunkHashMap = {};
  82. Object.keys(chunkMaps.hash).forEach(function(chunkId) {
  83. if(typeof chunkMaps.hash[chunkId] === "string")
  84. shortChunkHashMap[chunkId] = chunkMaps.hash[chunkId].substr(0, length);
  85. });
  86. return "\" + " + JSON.stringify(shortChunkHashMap) + "[chunkId] + \"";
  87. },
  88. name: "\" + (" + JSON.stringify(chunkMaps.name) + "[chunkId]||chunkId) + \""
  89. }
  90. }) + ";",
  91. "require('fs').readFile(filename, 'utf-8', function(err, content) {",
  92. this.indent([
  93. "if(err) return reject(err);",
  94. "var chunk = {};",
  95. "require('vm').runInThisContext('(function(exports, require, __dirname, __filename) {' + content + '\\n})', filename)" +
  96. "(chunk, require, require('path').dirname(filename), filename);"
  97. ].concat(insertMoreModules).concat([
  98. "var callbacks = [];",
  99. "for(var i = 0; i < chunkIds.length; i++) {",
  100. this.indent([
  101. "if(installedChunks[chunkIds[i]])",
  102. this.indent([
  103. "callbacks = callbacks.concat(installedChunks[chunkIds[i]][0]);"
  104. ]),
  105. "installedChunks[chunkIds[i]] = 0;"
  106. ]),
  107. "}",
  108. "for(i = 0; i < callbacks.length; i++)",
  109. this.indent("callbacks[i]();")
  110. ])),
  111. "});"
  112. ]),
  113. "});",
  114. "return installedChunks[chunkId][2] = promise;"
  115. ]);
  116. } else {
  117. var request = this.applyPluginsWaterfall("asset-path", JSON.stringify("./" + chunkFilename), {
  118. hash: "\" + " + this.renderCurrentHashCode(hash) + " + \"",
  119. hashWithLength: function(length) {
  120. return "\" + " + this.renderCurrentHashCode(hash, length) + " + \"";
  121. }.bind(this),
  122. chunk: {
  123. id: "\" + chunkId + \"",
  124. hash: "\" + " + JSON.stringify(chunkMaps.hash) + "[chunkId] + \"",
  125. hashWithLength: function(length) {
  126. var shortChunkHashMap = {};
  127. Object.keys(chunkMaps.hash).forEach(function(chunkId) {
  128. if(typeof chunkMaps.hash[chunkId] === "string")
  129. shortChunkHashMap[chunkId] = chunkMaps.hash[chunkId].substr(0, length);
  130. });
  131. return "\" + " + JSON.stringify(shortChunkHashMap) + "[chunkId] + \"";
  132. },
  133. name: "\" + (" + JSON.stringify(chunkMaps.name) + "[chunkId]||chunkId) + \""
  134. }
  135. });
  136. return this.asString([
  137. "// \"0\" is the signal for \"already loaded\"",
  138. "if(installedChunks[chunkId] !== 0) {",
  139. this.indent([
  140. "var chunk = require(" + request + ");"
  141. ].concat(insertMoreModules).concat([
  142. "for(var i = 0; i < chunkIds.length; i++)",
  143. this.indent("installedChunks[chunkIds[i]] = 0;")
  144. ])),
  145. "}",
  146. "return Promise.resolve();"
  147. ]);
  148. }
  149. });
  150. mainTemplate.plugin("hot-bootstrap", function(source, chunk, hash) {
  151. var hotUpdateChunkFilename = this.outputOptions.hotUpdateChunkFilename;
  152. var hotUpdateMainFilename = this.outputOptions.hotUpdateMainFilename;
  153. var chunkMaps = chunk.getChunkMaps();
  154. var currentHotUpdateChunkFilename = this.applyPluginsWaterfall("asset-path", JSON.stringify(hotUpdateChunkFilename), {
  155. hash: "\" + " + this.renderCurrentHashCode(hash) + " + \"",
  156. hashWithLength: function(length) {
  157. return "\" + " + this.renderCurrentHashCode(hash, length) + " + \"";
  158. }.bind(this),
  159. chunk: {
  160. id: "\" + chunkId + \"",
  161. hash: "\" + " + JSON.stringify(chunkMaps.hash) + "[chunkId] + \"",
  162. hashWithLength: function(length) {
  163. var shortChunkHashMap = {};
  164. Object.keys(chunkMaps.hash).forEach(function(chunkId) {
  165. if(typeof chunkMaps.hash[chunkId] === "string")
  166. shortChunkHashMap[chunkId] = chunkMaps.hash[chunkId].substr(0, length);
  167. });
  168. return "\" + " + JSON.stringify(shortChunkHashMap) + "[chunkId] + \"";
  169. },
  170. name: "\" + (" + JSON.stringify(chunkMaps.name) + "[chunkId]||chunkId) + \""
  171. }
  172. });
  173. var currentHotUpdateMainFilename = this.applyPluginsWaterfall("asset-path", JSON.stringify(hotUpdateMainFilename), {
  174. hash: "\" + " + this.renderCurrentHashCode(hash) + " + \"",
  175. hashWithLength: function(length) {
  176. return "\" + " + this.renderCurrentHashCode(hash, length) + " + \"";
  177. }.bind(this)
  178. });
  179. return Template.getFunctionContent(self.asyncChunkLoading ? require("./NodeMainTemplateAsync.runtime.js") : require("./NodeMainTemplate.runtime.js"))
  180. .replace(/\$require\$/g, this.requireFn)
  181. .replace(/\$hotMainFilename\$/g, currentHotUpdateMainFilename)
  182. .replace(/\$hotChunkFilename\$/g, currentHotUpdateChunkFilename);
  183. });
  184. mainTemplate.plugin("hash", function(hash) {
  185. hash.update("node");
  186. hash.update("3");
  187. hash.update(this.outputOptions.filename + "");
  188. hash.update(this.outputOptions.chunkFilename + "");
  189. });
  190. };