| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 | /*	MIT License http://www.opensource.org/licenses/mit-license.php*/"use strict";const RuntimeGlobals = require("../RuntimeGlobals");const RuntimeModule = require("../RuntimeModule");const Template = require("../Template");const {	chunkHasJs,	getChunkFilenameTemplate} = require("../javascript/JavascriptModulesPlugin");const { getInitialChunkIds } = require("../javascript/StartupHelpers");const compileBooleanMatcher = require("../util/compileBooleanMatcher");const { getUndoPath } = require("../util/identifier");/** @typedef {import("../Chunk")} Chunk */class RequireChunkLoadingRuntimeModule extends RuntimeModule {	constructor(runtimeRequirements) {		super("require chunk loading", RuntimeModule.STAGE_ATTACH);		this.runtimeRequirements = runtimeRequirements;	}	/**	 * @private	 * @param {Chunk} chunk chunk	 * @param {string} rootOutputDir root output directory	 * @returns {string} generated code	 */	_generateBaseUri(chunk, rootOutputDir) {		const options = chunk.getEntryOptions();		if (options && options.baseUri) {			return `${RuntimeGlobals.baseURI} = ${JSON.stringify(options.baseUri)};`;		}		return `${RuntimeGlobals.baseURI} = require("url").pathToFileURL(${			rootOutputDir !== "./"				? `__dirname + ${JSON.stringify("/" + rootOutputDir)}`				: "__filename"		});`;	}	/**	 * @returns {string} runtime code	 */	generate() {		const { chunkGraph, chunk } = this;		const { runtimeTemplate } = this.compilation;		const fn = RuntimeGlobals.ensureChunkHandlers;		const withBaseURI = this.runtimeRequirements.has(RuntimeGlobals.baseURI);		const withExternalInstallChunk = this.runtimeRequirements.has(			RuntimeGlobals.externalInstallChunk		);		const withOnChunkLoad = this.runtimeRequirements.has(			RuntimeGlobals.onChunksLoaded		);		const withLoading = this.runtimeRequirements.has(			RuntimeGlobals.ensureChunkHandlers		);		const withHmr = this.runtimeRequirements.has(			RuntimeGlobals.hmrDownloadUpdateHandlers		);		const withHmrManifest = this.runtimeRequirements.has(			RuntimeGlobals.hmrDownloadManifest		);		const conditionMap = chunkGraph.getChunkConditionMap(chunk, chunkHasJs);		const hasJsMatcher = compileBooleanMatcher(conditionMap);		const initialChunkIds = getInitialChunkIds(chunk, chunkGraph, chunkHasJs);		const outputName = this.compilation.getPath(			getChunkFilenameTemplate(chunk, this.compilation.outputOptions),			{				chunk,				contentHashType: "javascript"			}		);		const rootOutputDir = getUndoPath(			outputName,			this.compilation.outputOptions.path,			true		);		const stateExpression = withHmr			? `${RuntimeGlobals.hmrRuntimeStatePrefix}_require`			: undefined;		return Template.asString([			withBaseURI				? this._generateBaseUri(chunk, rootOutputDir)				: "// no baseURI",			"",			"// object to store loaded chunks",			'// "1" means "loaded", otherwise not loaded yet',			`var installedChunks = ${				stateExpression ? `${stateExpression} = ${stateExpression} || ` : ""			}{`,			Template.indent(				Array.from(initialChunkIds, id => `${JSON.stringify(id)}: 1`).join(					",\n"				)			),			"};",			"",			withOnChunkLoad				? `${						RuntimeGlobals.onChunksLoaded				  }.require = ${runtimeTemplate.returningFunction(						"installedChunks[chunkId]",						"chunkId"				  )};`				: "// no on chunks loaded",			"",			withLoading || withExternalInstallChunk				? `var installChunk = ${runtimeTemplate.basicFunction("chunk", [						"var moreModules = chunk.modules, chunkIds = chunk.ids, runtime = chunk.runtime;",						"for(var moduleId in moreModules) {",						Template.indent([							`if(${RuntimeGlobals.hasOwnProperty}(moreModules, moduleId)) {`,							Template.indent([								`${RuntimeGlobals.moduleFactories}[moduleId] = moreModules[moduleId];`							]),							"}"						]),						"}",						`if(runtime) runtime(__webpack_require__);`,						"for(var i = 0; i < chunkIds.length; i++)",						Template.indent("installedChunks[chunkIds[i]] = 1;"),						withOnChunkLoad ? `${RuntimeGlobals.onChunksLoaded}();` : ""				  ])};`				: "// no chunk install function needed",			"",			withLoading				? Template.asString([						"// require() chunk loading for javascript",						`${fn}.require = ${runtimeTemplate.basicFunction(							"chunkId, promises",							hasJsMatcher !== false								? [										'// "1" is the signal for "already loaded"',										"if(!installedChunks[chunkId]) {",										Template.indent([											hasJsMatcher === true												? "if(true) { // all chunks have JS"												: `if(${hasJsMatcher("chunkId")}) {`,											Template.indent([												`installChunk(require(${JSON.stringify(													rootOutputDir												)} + ${													RuntimeGlobals.getChunkScriptFilename												}(chunkId)));`											]),											"} else installedChunks[chunkId] = 1;",											""										]),										"}"								  ]								: "installedChunks[chunkId] = 1;"						)};`				  ])				: "// no chunk loading",			"",			withExternalInstallChunk				? Template.asString([						"module.exports = __webpack_require__;",						`${RuntimeGlobals.externalInstallChunk} = installChunk;`				  ])				: "// no external install chunk",			"",			withHmr				? Template.asString([						"function loadUpdateChunk(chunkId, updatedModulesList) {",						Template.indent([							`var update = require(${JSON.stringify(rootOutputDir)} + ${								RuntimeGlobals.getChunkUpdateScriptFilename							}(chunkId));`,							"var updatedModules = update.modules;",							"var runtime = update.runtime;",							"for(var moduleId in updatedModules) {",							Template.indent([								`if(${RuntimeGlobals.hasOwnProperty}(updatedModules, moduleId)) {`,								Template.indent([									`currentUpdate[moduleId] = updatedModules[moduleId];`,									"if(updatedModulesList) updatedModulesList.push(moduleId);"								]),								"}"							]),							"}",							"if(runtime) currentUpdateRuntime.push(runtime);"						]),						"}",						"",						Template.getFunctionContent(							require("../hmr/JavascriptHotModuleReplacement.runtime.js")						)							.replace(/\$key\$/g, "require")							.replace(/\$installedChunks\$/g, "installedChunks")							.replace(/\$loadUpdateChunk\$/g, "loadUpdateChunk")							.replace(/\$moduleCache\$/g, RuntimeGlobals.moduleCache)							.replace(/\$moduleFactories\$/g, RuntimeGlobals.moduleFactories)							.replace(								/\$ensureChunkHandlers\$/g,								RuntimeGlobals.ensureChunkHandlers							)							.replace(/\$hasOwnProperty\$/g, RuntimeGlobals.hasOwnProperty)							.replace(/\$hmrModuleData\$/g, RuntimeGlobals.hmrModuleData)							.replace(								/\$hmrDownloadUpdateHandlers\$/g,								RuntimeGlobals.hmrDownloadUpdateHandlers							)							.replace(								/\$hmrInvalidateModuleHandlers\$/g,								RuntimeGlobals.hmrInvalidateModuleHandlers							)				  ])				: "// no HMR",			"",			withHmrManifest				? Template.asString([						`${RuntimeGlobals.hmrDownloadManifest} = function() {`,						Template.indent([							"return Promise.resolve().then(function() {",							Template.indent([								`return require(${JSON.stringify(rootOutputDir)} + ${									RuntimeGlobals.getUpdateManifestFilename								}());`							]),							"})['catch'](function(err) { if(err.code !== 'MODULE_NOT_FOUND') throw err; });"						]),						"}"				  ])				: "// no HMR manifest"		]);	}}module.exports = RequireChunkLoadingRuntimeModule;
 |