RuntimePlugin.js 15 KB

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