MainTemplate.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const { SyncWaterfallHook } = require("tapable");
  7. const util = require("util");
  8. const RuntimeGlobals = require("./RuntimeGlobals");
  9. const memoize = require("./util/memoize");
  10. /** @typedef {import("webpack-sources").ConcatSource} ConcatSource */
  11. /** @typedef {import("webpack-sources").Source} Source */
  12. /** @typedef {import("../declarations/WebpackOptions").Output} OutputOptions */
  13. /** @typedef {import("./ModuleTemplate")} ModuleTemplate */
  14. /** @typedef {import("./Chunk")} Chunk */
  15. /** @typedef {import("./Compilation")} Compilation */
  16. /** @typedef {import("./Compilation").AssetInfo} AssetInfo */
  17. /** @typedef {import("./Module")} Module} */
  18. /** @typedef {import("./util/Hash")} Hash} */
  19. /** @typedef {import("./DependencyTemplates")} DependencyTemplates} */
  20. /** @typedef {import("./javascript/JavascriptModulesPlugin").RenderContext} RenderContext} */
  21. /** @typedef {import("./RuntimeTemplate")} RuntimeTemplate} */
  22. /** @typedef {import("./ModuleGraph")} ModuleGraph} */
  23. /** @typedef {import("./ChunkGraph")} ChunkGraph} */
  24. /** @typedef {import("./Template").RenderManifestOptions} RenderManifestOptions} */
  25. /** @typedef {import("./Template").RenderManifestEntry} RenderManifestEntry} */
  26. const getJavascriptModulesPlugin = memoize(() =>
  27. require("./javascript/JavascriptModulesPlugin")
  28. );
  29. const getJsonpTemplatePlugin = memoize(() =>
  30. require("./web/JsonpTemplatePlugin")
  31. );
  32. const getLoadScriptRuntimeModule = memoize(() =>
  33. require("./runtime/LoadScriptRuntimeModule")
  34. );
  35. // TODO webpack 6 remove this class
  36. class MainTemplate {
  37. /**
  38. *
  39. * @param {OutputOptions} outputOptions output options for the MainTemplate
  40. * @param {Compilation} compilation the compilation
  41. */
  42. constructor(outputOptions, compilation) {
  43. /** @type {OutputOptions} */
  44. this._outputOptions = outputOptions || {};
  45. this.hooks = Object.freeze({
  46. renderManifest: {
  47. tap: util.deprecate(
  48. (options, fn) => {
  49. compilation.hooks.renderManifest.tap(
  50. options,
  51. (entries, options) => {
  52. if (!options.chunk.hasRuntime()) return entries;
  53. return fn(entries, options);
  54. }
  55. );
  56. },
  57. "MainTemplate.hooks.renderManifest is deprecated (use Compilation.hooks.renderManifest instead)",
  58. "DEP_WEBPACK_MAIN_TEMPLATE_RENDER_MANIFEST"
  59. )
  60. },
  61. modules: {
  62. tap: () => {
  63. throw new Error(
  64. "MainTemplate.hooks.modules has been removed (there is no replacement, please create an issue to request that)"
  65. );
  66. }
  67. },
  68. moduleObj: {
  69. tap: () => {
  70. throw new Error(
  71. "MainTemplate.hooks.moduleObj has been removed (there is no replacement, please create an issue to request that)"
  72. );
  73. }
  74. },
  75. require: {
  76. tap: util.deprecate(
  77. (options, fn) => {
  78. getJavascriptModulesPlugin()
  79. .getCompilationHooks(compilation)
  80. .renderRequire.tap(options, fn);
  81. },
  82. "MainTemplate.hooks.require is deprecated (use JavascriptModulesPlugin.getCompilationHooks().renderRequire instead)",
  83. "DEP_WEBPACK_MAIN_TEMPLATE_REQUIRE"
  84. )
  85. },
  86. beforeStartup: {
  87. tap: () => {
  88. throw new Error(
  89. "MainTemplate.hooks.beforeStartup has been removed (use RuntimeGlobals.startupOnlyBefore instead)"
  90. );
  91. }
  92. },
  93. startup: {
  94. tap: () => {
  95. throw new Error(
  96. "MainTemplate.hooks.startup has been removed (use RuntimeGlobals.startup instead)"
  97. );
  98. }
  99. },
  100. afterStartup: {
  101. tap: () => {
  102. throw new Error(
  103. "MainTemplate.hooks.afterStartup has been removed (use RuntimeGlobals.startupOnlyAfter instead)"
  104. );
  105. }
  106. },
  107. render: {
  108. tap: util.deprecate(
  109. (options, fn) => {
  110. getJavascriptModulesPlugin()
  111. .getCompilationHooks(compilation)
  112. .render.tap(options, (source, renderContext) => {
  113. if (
  114. renderContext.chunkGraph.getNumberOfEntryModules(
  115. renderContext.chunk
  116. ) === 0 ||
  117. !renderContext.chunk.hasRuntime()
  118. ) {
  119. return source;
  120. }
  121. return fn(
  122. source,
  123. renderContext.chunk,
  124. compilation.hash,
  125. compilation.moduleTemplates.javascript,
  126. compilation.dependencyTemplates
  127. );
  128. });
  129. },
  130. "MainTemplate.hooks.render is deprecated (use JavascriptModulesPlugin.getCompilationHooks().render instead)",
  131. "DEP_WEBPACK_MAIN_TEMPLATE_RENDER"
  132. )
  133. },
  134. renderWithEntry: {
  135. tap: util.deprecate(
  136. (options, fn) => {
  137. getJavascriptModulesPlugin()
  138. .getCompilationHooks(compilation)
  139. .render.tap(options, (source, renderContext) => {
  140. if (
  141. renderContext.chunkGraph.getNumberOfEntryModules(
  142. renderContext.chunk
  143. ) === 0 ||
  144. !renderContext.chunk.hasRuntime()
  145. ) {
  146. return source;
  147. }
  148. return fn(source, renderContext.chunk, compilation.hash);
  149. });
  150. },
  151. "MainTemplate.hooks.renderWithEntry is deprecated (use JavascriptModulesPlugin.getCompilationHooks().render instead)",
  152. "DEP_WEBPACK_MAIN_TEMPLATE_RENDER_WITH_ENTRY"
  153. )
  154. },
  155. assetPath: {
  156. tap: util.deprecate(
  157. (options, fn) => {
  158. compilation.hooks.assetPath.tap(options, fn);
  159. },
  160. "MainTemplate.hooks.assetPath is deprecated (use Compilation.hooks.assetPath instead)",
  161. "DEP_WEBPACK_MAIN_TEMPLATE_ASSET_PATH"
  162. ),
  163. call: util.deprecate(
  164. (filename, options) => {
  165. return compilation.getAssetPath(filename, options);
  166. },
  167. "MainTemplate.hooks.assetPath is deprecated (use Compilation.hooks.assetPath instead)",
  168. "DEP_WEBPACK_MAIN_TEMPLATE_ASSET_PATH"
  169. )
  170. },
  171. hash: {
  172. tap: util.deprecate(
  173. (options, fn) => {
  174. compilation.hooks.fullHash.tap(options, fn);
  175. },
  176. "MainTemplate.hooks.hash is deprecated (use Compilation.hooks.fullHash instead)",
  177. "DEP_WEBPACK_MAIN_TEMPLATE_HASH"
  178. )
  179. },
  180. hashForChunk: {
  181. tap: util.deprecate(
  182. (options, fn) => {
  183. getJavascriptModulesPlugin()
  184. .getCompilationHooks(compilation)
  185. .chunkHash.tap(options, (chunk, hash) => {
  186. if (!chunk.hasRuntime()) return;
  187. return fn(hash, chunk);
  188. });
  189. },
  190. "MainTemplate.hooks.hashForChunk is deprecated (use JavascriptModulesPlugin.getCompilationHooks().chunkHash instead)",
  191. "DEP_WEBPACK_MAIN_TEMPLATE_HASH_FOR_CHUNK"
  192. )
  193. },
  194. globalHashPaths: {
  195. tap: util.deprecate(
  196. () => {},
  197. "MainTemplate.hooks.globalHashPaths has been removed (it's no longer needed)",
  198. "DEP_WEBPACK_MAIN_TEMPLATE_HASH_FOR_CHUNK"
  199. )
  200. },
  201. globalHash: {
  202. tap: util.deprecate(
  203. () => {},
  204. "MainTemplate.hooks.globalHash has been removed (it's no longer needed)",
  205. "DEP_WEBPACK_MAIN_TEMPLATE_HASH_FOR_CHUNK"
  206. )
  207. },
  208. hotBootstrap: {
  209. tap: () => {
  210. throw new Error(
  211. "MainTemplate.hooks.hotBootstrap has been removed (use your own RuntimeModule instead)"
  212. );
  213. }
  214. },
  215. // for compatibility:
  216. /** @type {SyncWaterfallHook<[string, Chunk, string, ModuleTemplate, DependencyTemplates]>} */
  217. bootstrap: new SyncWaterfallHook([
  218. "source",
  219. "chunk",
  220. "hash",
  221. "moduleTemplate",
  222. "dependencyTemplates"
  223. ]),
  224. /** @type {SyncWaterfallHook<[string, Chunk, string]>} */
  225. localVars: new SyncWaterfallHook(["source", "chunk", "hash"]),
  226. /** @type {SyncWaterfallHook<[string, Chunk, string]>} */
  227. requireExtensions: new SyncWaterfallHook(["source", "chunk", "hash"]),
  228. /** @type {SyncWaterfallHook<[string, Chunk, string, string]>} */
  229. requireEnsure: new SyncWaterfallHook([
  230. "source",
  231. "chunk",
  232. "hash",
  233. "chunkIdExpression"
  234. ]),
  235. get jsonpScript() {
  236. const hooks =
  237. getLoadScriptRuntimeModule().getCompilationHooks(compilation);
  238. return hooks.createScript;
  239. },
  240. get linkPrefetch() {
  241. const hooks = getJsonpTemplatePlugin().getCompilationHooks(compilation);
  242. return hooks.linkPrefetch;
  243. },
  244. get linkPreload() {
  245. const hooks = getJsonpTemplatePlugin().getCompilationHooks(compilation);
  246. return hooks.linkPreload;
  247. }
  248. });
  249. this.renderCurrentHashCode = util.deprecate(
  250. /**
  251. * @deprecated
  252. * @param {string} hash the hash
  253. * @param {number=} length length of the hash
  254. * @returns {string} generated code
  255. */ (hash, length) => {
  256. if (length) {
  257. return `${RuntimeGlobals.getFullHash} ? ${
  258. RuntimeGlobals.getFullHash
  259. }().slice(0, ${length}) : ${hash.slice(0, length)}`;
  260. }
  261. return `${RuntimeGlobals.getFullHash} ? ${RuntimeGlobals.getFullHash}() : ${hash}`;
  262. },
  263. "MainTemplate.renderCurrentHashCode is deprecated (use RuntimeGlobals.getFullHash runtime function instead)",
  264. "DEP_WEBPACK_MAIN_TEMPLATE_RENDER_CURRENT_HASH_CODE"
  265. );
  266. this.getPublicPath = util.deprecate(
  267. /**
  268. *
  269. * @param {object} options get public path options
  270. * @returns {string} hook call
  271. */ options => {
  272. return compilation.getAssetPath(
  273. compilation.outputOptions.publicPath,
  274. options
  275. );
  276. },
  277. "MainTemplate.getPublicPath is deprecated (use Compilation.getAssetPath(compilation.outputOptions.publicPath, options) instead)",
  278. "DEP_WEBPACK_MAIN_TEMPLATE_GET_PUBLIC_PATH"
  279. );
  280. this.getAssetPath = util.deprecate(
  281. (path, options) => {
  282. return compilation.getAssetPath(path, options);
  283. },
  284. "MainTemplate.getAssetPath is deprecated (use Compilation.getAssetPath instead)",
  285. "DEP_WEBPACK_MAIN_TEMPLATE_GET_ASSET_PATH"
  286. );
  287. this.getAssetPathWithInfo = util.deprecate(
  288. (path, options) => {
  289. return compilation.getAssetPathWithInfo(path, options);
  290. },
  291. "MainTemplate.getAssetPathWithInfo is deprecated (use Compilation.getAssetPath instead)",
  292. "DEP_WEBPACK_MAIN_TEMPLATE_GET_ASSET_PATH_WITH_INFO"
  293. );
  294. }
  295. }
  296. Object.defineProperty(MainTemplate.prototype, "requireFn", {
  297. get: util.deprecate(
  298. () => RuntimeGlobals.require,
  299. `MainTemplate.requireFn is deprecated (use "${RuntimeGlobals.require}")`,
  300. "DEP_WEBPACK_MAIN_TEMPLATE_REQUIRE_FN"
  301. )
  302. });
  303. Object.defineProperty(MainTemplate.prototype, "outputOptions", {
  304. get: util.deprecate(
  305. /**
  306. * @this {MainTemplate}
  307. * @returns {OutputOptions} output options
  308. */
  309. function () {
  310. return this._outputOptions;
  311. },
  312. "MainTemplate.outputOptions is deprecated (use Compilation.outputOptions instead)",
  313. "DEP_WEBPACK_MAIN_TEMPLATE_OUTPUT_OPTIONS"
  314. )
  315. });
  316. module.exports = MainTemplate;