10
0

RuntimePlugin.js 17 KB

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