RuntimePlugin.js 16 KB

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