RuntimePlugin.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const RuntimeGlobals = require("./RuntimeGlobals");
  7. const { getChunkFilenameTemplate } = require("./css/CssModulesPlugin");
  8. const RuntimeRequirementsDependency = require("./dependencies/RuntimeRequirementsDependency");
  9. const JavascriptModulesPlugin = require("./javascript/JavascriptModulesPlugin");
  10. const AsyncModuleRuntimeModule = require("./runtime/AsyncModuleRuntimeModule");
  11. const AutoPublicPathRuntimeModule = require("./runtime/AutoPublicPathRuntimeModule");
  12. const CompatGetDefaultExportRuntimeModule = require("./runtime/CompatGetDefaultExportRuntimeModule");
  13. const CompatRuntimeModule = require("./runtime/CompatRuntimeModule");
  14. const CreateFakeNamespaceObjectRuntimeModule = require("./runtime/CreateFakeNamespaceObjectRuntimeModule");
  15. const CreateScriptRuntimeModule = require("./runtime/CreateScriptRuntimeModule");
  16. const CreateScriptUrlRuntimeModule = require("./runtime/CreateScriptUrlRuntimeModule");
  17. const DefinePropertyGettersRuntimeModule = require("./runtime/DefinePropertyGettersRuntimeModule");
  18. const EnsureChunkRuntimeModule = require("./runtime/EnsureChunkRuntimeModule");
  19. const GetChunkFilenameRuntimeModule = require("./runtime/GetChunkFilenameRuntimeModule");
  20. const GetMainFilenameRuntimeModule = require("./runtime/GetMainFilenameRuntimeModule");
  21. const GetTrustedTypesPolicyRuntimeModule = require("./runtime/GetTrustedTypesPolicyRuntimeModule");
  22. const GlobalRuntimeModule = require("./runtime/GlobalRuntimeModule");
  23. const HasOwnPropertyRuntimeModule = require("./runtime/HasOwnPropertyRuntimeModule");
  24. const LoadScriptRuntimeModule = require("./runtime/LoadScriptRuntimeModule");
  25. const MakeNamespaceObjectRuntimeModule = require("./runtime/MakeNamespaceObjectRuntimeModule");
  26. const OnChunksLoadedRuntimeModule = require("./runtime/OnChunksLoadedRuntimeModule");
  27. const PublicPathRuntimeModule = require("./runtime/PublicPathRuntimeModule");
  28. const RelativeUrlRuntimeModule = require("./runtime/RelativeUrlRuntimeModule");
  29. const RuntimeIdRuntimeModule = require("./runtime/RuntimeIdRuntimeModule");
  30. const SystemContextRuntimeModule = require("./runtime/SystemContextRuntimeModule");
  31. const ShareRuntimeModule = require("./sharing/ShareRuntimeModule");
  32. const StringXor = require("./util/StringXor");
  33. /** @typedef {import("./Chunk")} Chunk */
  34. /** @typedef {import("./Compiler")} Compiler */
  35. /** @typedef {import("./Module")} Module */
  36. const GLOBALS_ON_REQUIRE = [
  37. RuntimeGlobals.chunkName,
  38. RuntimeGlobals.runtimeId,
  39. RuntimeGlobals.compatGetDefaultExport,
  40. RuntimeGlobals.createFakeNamespaceObject,
  41. RuntimeGlobals.createScript,
  42. RuntimeGlobals.createScriptUrl,
  43. RuntimeGlobals.getTrustedTypesPolicy,
  44. RuntimeGlobals.definePropertyGetters,
  45. RuntimeGlobals.ensureChunk,
  46. RuntimeGlobals.entryModuleId,
  47. RuntimeGlobals.getFullHash,
  48. RuntimeGlobals.global,
  49. RuntimeGlobals.makeNamespaceObject,
  50. RuntimeGlobals.moduleCache,
  51. RuntimeGlobals.moduleFactories,
  52. RuntimeGlobals.moduleFactoriesAddOnly,
  53. RuntimeGlobals.interceptModuleExecution,
  54. RuntimeGlobals.publicPath,
  55. RuntimeGlobals.baseURI,
  56. RuntimeGlobals.relativeUrl,
  57. RuntimeGlobals.scriptNonce,
  58. RuntimeGlobals.uncaughtErrorHandler,
  59. RuntimeGlobals.asyncModule,
  60. RuntimeGlobals.wasmInstances,
  61. RuntimeGlobals.instantiateWasm,
  62. RuntimeGlobals.shareScopeMap,
  63. RuntimeGlobals.initializeSharing,
  64. RuntimeGlobals.loadScript,
  65. RuntimeGlobals.systemContext,
  66. RuntimeGlobals.onChunksLoaded
  67. ];
  68. const MODULE_DEPENDENCIES = {
  69. [RuntimeGlobals.moduleLoaded]: [RuntimeGlobals.module],
  70. [RuntimeGlobals.moduleId]: [RuntimeGlobals.module]
  71. };
  72. const TREE_DEPENDENCIES = {
  73. [RuntimeGlobals.definePropertyGetters]: [RuntimeGlobals.hasOwnProperty],
  74. [RuntimeGlobals.compatGetDefaultExport]: [
  75. RuntimeGlobals.definePropertyGetters
  76. ],
  77. [RuntimeGlobals.createFakeNamespaceObject]: [
  78. RuntimeGlobals.definePropertyGetters,
  79. RuntimeGlobals.makeNamespaceObject,
  80. RuntimeGlobals.require
  81. ],
  82. [RuntimeGlobals.initializeSharing]: [RuntimeGlobals.shareScopeMap],
  83. [RuntimeGlobals.shareScopeMap]: [RuntimeGlobals.hasOwnProperty]
  84. };
  85. class RuntimePlugin {
  86. /**
  87. * @param {Compiler} compiler the Compiler
  88. * @returns {void}
  89. */
  90. apply(compiler) {
  91. compiler.hooks.compilation.tap("RuntimePlugin", compilation => {
  92. compilation.dependencyTemplates.set(
  93. RuntimeRequirementsDependency,
  94. new RuntimeRequirementsDependency.Template()
  95. );
  96. for (const req of GLOBALS_ON_REQUIRE) {
  97. compilation.hooks.runtimeRequirementInModule
  98. .for(req)
  99. .tap("RuntimePlugin", (module, set) => {
  100. set.add(RuntimeGlobals.requireScope);
  101. });
  102. compilation.hooks.runtimeRequirementInTree
  103. .for(req)
  104. .tap("RuntimePlugin", (module, set) => {
  105. set.add(RuntimeGlobals.requireScope);
  106. });
  107. }
  108. for (const req of Object.keys(TREE_DEPENDENCIES)) {
  109. const deps = TREE_DEPENDENCIES[req];
  110. compilation.hooks.runtimeRequirementInTree
  111. .for(req)
  112. .tap("RuntimePlugin", (chunk, set) => {
  113. for (const dep of deps) set.add(dep);
  114. });
  115. }
  116. for (const req of Object.keys(MODULE_DEPENDENCIES)) {
  117. const deps = MODULE_DEPENDENCIES[req];
  118. compilation.hooks.runtimeRequirementInModule
  119. .for(req)
  120. .tap("RuntimePlugin", (chunk, set) => {
  121. for (const dep of deps) set.add(dep);
  122. });
  123. }
  124. compilation.hooks.runtimeRequirementInTree
  125. .for(RuntimeGlobals.definePropertyGetters)
  126. .tap("RuntimePlugin", chunk => {
  127. compilation.addRuntimeModule(
  128. chunk,
  129. new DefinePropertyGettersRuntimeModule()
  130. );
  131. return true;
  132. });
  133. compilation.hooks.runtimeRequirementInTree
  134. .for(RuntimeGlobals.makeNamespaceObject)
  135. .tap("RuntimePlugin", chunk => {
  136. compilation.addRuntimeModule(
  137. chunk,
  138. new MakeNamespaceObjectRuntimeModule()
  139. );
  140. return true;
  141. });
  142. compilation.hooks.runtimeRequirementInTree
  143. .for(RuntimeGlobals.createFakeNamespaceObject)
  144. .tap("RuntimePlugin", chunk => {
  145. compilation.addRuntimeModule(
  146. chunk,
  147. new CreateFakeNamespaceObjectRuntimeModule()
  148. );
  149. return true;
  150. });
  151. compilation.hooks.runtimeRequirementInTree
  152. .for(RuntimeGlobals.hasOwnProperty)
  153. .tap("RuntimePlugin", chunk => {
  154. compilation.addRuntimeModule(
  155. chunk,
  156. new HasOwnPropertyRuntimeModule()
  157. );
  158. return true;
  159. });
  160. compilation.hooks.runtimeRequirementInTree
  161. .for(RuntimeGlobals.compatGetDefaultExport)
  162. .tap("RuntimePlugin", chunk => {
  163. compilation.addRuntimeModule(
  164. chunk,
  165. new CompatGetDefaultExportRuntimeModule()
  166. );
  167. return true;
  168. });
  169. compilation.hooks.runtimeRequirementInTree
  170. .for(RuntimeGlobals.runtimeId)
  171. .tap("RuntimePlugin", chunk => {
  172. compilation.addRuntimeModule(chunk, new RuntimeIdRuntimeModule());
  173. return true;
  174. });
  175. compilation.hooks.runtimeRequirementInTree
  176. .for(RuntimeGlobals.publicPath)
  177. .tap("RuntimePlugin", (chunk, set) => {
  178. const { outputOptions } = compilation;
  179. const { publicPath: globalPublicPath, scriptType } = outputOptions;
  180. const entryOptions = chunk.getEntryOptions();
  181. const publicPath =
  182. entryOptions && entryOptions.publicPath !== undefined
  183. ? entryOptions.publicPath
  184. : globalPublicPath;
  185. if (publicPath === "auto") {
  186. const module = new AutoPublicPathRuntimeModule();
  187. if (scriptType !== "module") set.add(RuntimeGlobals.global);
  188. compilation.addRuntimeModule(chunk, module);
  189. } else {
  190. const module = new PublicPathRuntimeModule(publicPath);
  191. if (
  192. typeof publicPath !== "string" ||
  193. /\[(full)?hash\]/.test(publicPath)
  194. ) {
  195. module.fullHash = true;
  196. }
  197. compilation.addRuntimeModule(chunk, module);
  198. }
  199. return true;
  200. });
  201. compilation.hooks.runtimeRequirementInTree
  202. .for(RuntimeGlobals.global)
  203. .tap("RuntimePlugin", chunk => {
  204. compilation.addRuntimeModule(chunk, new GlobalRuntimeModule());
  205. return true;
  206. });
  207. compilation.hooks.runtimeRequirementInTree
  208. .for(RuntimeGlobals.asyncModule)
  209. .tap("RuntimePlugin", chunk => {
  210. compilation.addRuntimeModule(chunk, new AsyncModuleRuntimeModule());
  211. return true;
  212. });
  213. compilation.hooks.runtimeRequirementInTree
  214. .for(RuntimeGlobals.systemContext)
  215. .tap("RuntimePlugin", chunk => {
  216. const { outputOptions } = compilation;
  217. const { library: globalLibrary } = outputOptions;
  218. const entryOptions = chunk.getEntryOptions();
  219. const libraryType =
  220. entryOptions && entryOptions.library !== undefined
  221. ? entryOptions.library.type
  222. : globalLibrary.type;
  223. if (libraryType === "system") {
  224. compilation.addRuntimeModule(
  225. chunk,
  226. new SystemContextRuntimeModule()
  227. );
  228. }
  229. return true;
  230. });
  231. compilation.hooks.runtimeRequirementInTree
  232. .for(RuntimeGlobals.getChunkScriptFilename)
  233. .tap("RuntimePlugin", (chunk, set) => {
  234. if (
  235. typeof compilation.outputOptions.chunkFilename === "string" &&
  236. /\[(full)?hash(:\d+)?\]/.test(
  237. compilation.outputOptions.chunkFilename
  238. )
  239. ) {
  240. set.add(RuntimeGlobals.getFullHash);
  241. }
  242. compilation.addRuntimeModule(
  243. chunk,
  244. new GetChunkFilenameRuntimeModule(
  245. "javascript",
  246. "javascript",
  247. RuntimeGlobals.getChunkScriptFilename,
  248. chunk =>
  249. chunk.filenameTemplate ||
  250. (chunk.canBeInitial()
  251. ? compilation.outputOptions.filename
  252. : compilation.outputOptions.chunkFilename),
  253. false
  254. )
  255. );
  256. return true;
  257. });
  258. compilation.hooks.runtimeRequirementInTree
  259. .for(RuntimeGlobals.getChunkCssFilename)
  260. .tap("RuntimePlugin", (chunk, set) => {
  261. if (
  262. typeof compilation.outputOptions.cssChunkFilename === "string" &&
  263. /\[(full)?hash(:\d+)?\]/.test(
  264. compilation.outputOptions.cssChunkFilename
  265. )
  266. ) {
  267. set.add(RuntimeGlobals.getFullHash);
  268. }
  269. compilation.addRuntimeModule(
  270. chunk,
  271. new GetChunkFilenameRuntimeModule(
  272. "css",
  273. "css",
  274. RuntimeGlobals.getChunkCssFilename,
  275. chunk =>
  276. getChunkFilenameTemplate(chunk, compilation.outputOptions),
  277. set.has(RuntimeGlobals.hmrDownloadUpdateHandlers)
  278. )
  279. );
  280. return true;
  281. });
  282. compilation.hooks.runtimeRequirementInTree
  283. .for(RuntimeGlobals.getChunkUpdateScriptFilename)
  284. .tap("RuntimePlugin", (chunk, set) => {
  285. if (
  286. /\[(full)?hash(:\d+)?\]/.test(
  287. compilation.outputOptions.hotUpdateChunkFilename
  288. )
  289. )
  290. set.add(RuntimeGlobals.getFullHash);
  291. compilation.addRuntimeModule(
  292. chunk,
  293. new GetChunkFilenameRuntimeModule(
  294. "javascript",
  295. "javascript update",
  296. RuntimeGlobals.getChunkUpdateScriptFilename,
  297. c => compilation.outputOptions.hotUpdateChunkFilename,
  298. true
  299. )
  300. );
  301. return true;
  302. });
  303. compilation.hooks.runtimeRequirementInTree
  304. .for(RuntimeGlobals.getUpdateManifestFilename)
  305. .tap("RuntimePlugin", (chunk, set) => {
  306. if (
  307. /\[(full)?hash(:\d+)?\]/.test(
  308. compilation.outputOptions.hotUpdateMainFilename
  309. )
  310. ) {
  311. set.add(RuntimeGlobals.getFullHash);
  312. }
  313. compilation.addRuntimeModule(
  314. chunk,
  315. new GetMainFilenameRuntimeModule(
  316. "update manifest",
  317. RuntimeGlobals.getUpdateManifestFilename,
  318. compilation.outputOptions.hotUpdateMainFilename
  319. )
  320. );
  321. return true;
  322. });
  323. compilation.hooks.runtimeRequirementInTree
  324. .for(RuntimeGlobals.ensureChunk)
  325. .tap("RuntimePlugin", (chunk, set) => {
  326. const hasAsyncChunks = chunk.hasAsyncChunks();
  327. if (hasAsyncChunks) {
  328. set.add(RuntimeGlobals.ensureChunkHandlers);
  329. }
  330. compilation.addRuntimeModule(
  331. chunk,
  332. new EnsureChunkRuntimeModule(set)
  333. );
  334. return true;
  335. });
  336. compilation.hooks.runtimeRequirementInTree
  337. .for(RuntimeGlobals.ensureChunkIncludeEntries)
  338. .tap("RuntimePlugin", (chunk, set) => {
  339. set.add(RuntimeGlobals.ensureChunkHandlers);
  340. });
  341. compilation.hooks.runtimeRequirementInTree
  342. .for(RuntimeGlobals.shareScopeMap)
  343. .tap("RuntimePlugin", (chunk, set) => {
  344. compilation.addRuntimeModule(chunk, new ShareRuntimeModule());
  345. return true;
  346. });
  347. compilation.hooks.runtimeRequirementInTree
  348. .for(RuntimeGlobals.loadScript)
  349. .tap("RuntimePlugin", (chunk, set) => {
  350. const withCreateScriptUrl = !!compilation.outputOptions.trustedTypes;
  351. if (withCreateScriptUrl) {
  352. set.add(RuntimeGlobals.createScriptUrl);
  353. }
  354. compilation.addRuntimeModule(
  355. chunk,
  356. new LoadScriptRuntimeModule(withCreateScriptUrl)
  357. );
  358. return true;
  359. });
  360. compilation.hooks.runtimeRequirementInTree
  361. .for(RuntimeGlobals.createScript)
  362. .tap("RuntimePlugin", (chunk, set) => {
  363. if (compilation.outputOptions.trustedTypes) {
  364. set.add(RuntimeGlobals.getTrustedTypesPolicy);
  365. }
  366. compilation.addRuntimeModule(chunk, new CreateScriptRuntimeModule());
  367. return true;
  368. });
  369. compilation.hooks.runtimeRequirementInTree
  370. .for(RuntimeGlobals.createScriptUrl)
  371. .tap("RuntimePlugin", (chunk, set) => {
  372. if (compilation.outputOptions.trustedTypes) {
  373. set.add(RuntimeGlobals.getTrustedTypesPolicy);
  374. }
  375. compilation.addRuntimeModule(
  376. chunk,
  377. new CreateScriptUrlRuntimeModule()
  378. );
  379. return true;
  380. });
  381. compilation.hooks.runtimeRequirementInTree
  382. .for(RuntimeGlobals.getTrustedTypesPolicy)
  383. .tap("RuntimePlugin", (chunk, set) => {
  384. compilation.addRuntimeModule(
  385. chunk,
  386. new GetTrustedTypesPolicyRuntimeModule(set)
  387. );
  388. return true;
  389. });
  390. compilation.hooks.runtimeRequirementInTree
  391. .for(RuntimeGlobals.relativeUrl)
  392. .tap("RuntimePlugin", (chunk, set) => {
  393. compilation.addRuntimeModule(chunk, new RelativeUrlRuntimeModule());
  394. return true;
  395. });
  396. compilation.hooks.runtimeRequirementInTree
  397. .for(RuntimeGlobals.onChunksLoaded)
  398. .tap("RuntimePlugin", (chunk, set) => {
  399. compilation.addRuntimeModule(
  400. chunk,
  401. new OnChunksLoadedRuntimeModule()
  402. );
  403. return true;
  404. });
  405. // TODO webpack 6: remove CompatRuntimeModule
  406. compilation.hooks.additionalTreeRuntimeRequirements.tap(
  407. "RuntimePlugin",
  408. (chunk, set) => {
  409. const { mainTemplate } = compilation;
  410. if (
  411. mainTemplate.hooks.bootstrap.isUsed() ||
  412. mainTemplate.hooks.localVars.isUsed() ||
  413. mainTemplate.hooks.requireEnsure.isUsed() ||
  414. mainTemplate.hooks.requireExtensions.isUsed()
  415. ) {
  416. compilation.addRuntimeModule(chunk, new CompatRuntimeModule());
  417. }
  418. }
  419. );
  420. JavascriptModulesPlugin.getCompilationHooks(compilation).chunkHash.tap(
  421. "RuntimePlugin",
  422. (chunk, hash, { chunkGraph }) => {
  423. const xor = new StringXor();
  424. for (const m of chunkGraph.getChunkRuntimeModulesIterable(chunk)) {
  425. xor.add(chunkGraph.getModuleHash(m, chunk.runtime));
  426. }
  427. xor.updateHash(hash);
  428. }
  429. );
  430. });
  431. }
  432. }
  433. module.exports = RuntimePlugin;