mirror of https://github.com/webpack/webpack.git
				
				
				
			
		
			
				
	
	
		
			198 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			198 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
| /*
 | |
| 	MIT License http://www.opensource.org/licenses/mit-license.php
 | |
| 	Author Tobias Koppers @sokra
 | |
| */
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| const HotModuleReplacementPlugin = require("../HotModuleReplacementPlugin");
 | |
| const Template = require("../Template");
 | |
| 
 | |
| /** @typedef {import("../MainTemplate")} MainTemplate */
 | |
| 
 | |
| class WebWorkerMainTemplatePlugin {
 | |
| 	/**
 | |
| 	 * @param {MainTemplate} mainTemplate the main template
 | |
| 	 * @returns {void}
 | |
| 	 */
 | |
| 	apply(mainTemplate) {
 | |
| 		const { hotBootstrap } = HotModuleReplacementPlugin.getMainTemplateHooks(
 | |
| 			mainTemplate
 | |
| 		);
 | |
| 		const needChunkOnDemandLoadingCode = chunk => {
 | |
| 			for (const chunkGroup of chunk.groupsIterable) {
 | |
| 				if (chunkGroup.getNumberOfChildren() > 0) return true;
 | |
| 			}
 | |
| 			return false;
 | |
| 		};
 | |
| 		mainTemplate.hooks.localVars.tap(
 | |
| 			"WebWorkerMainTemplatePlugin",
 | |
| 			(source, chunk) => {
 | |
| 				if (needChunkOnDemandLoadingCode(chunk)) {
 | |
| 					return Template.asString([
 | |
| 						source,
 | |
| 						"",
 | |
| 						"// object to store loaded chunks",
 | |
| 						'// "1" means "already loaded"',
 | |
| 						"var installedChunks = {",
 | |
| 						Template.indent(
 | |
| 							chunk.ids.map(id => `${JSON.stringify(id)}: 1`).join(",\n")
 | |
| 						),
 | |
| 						"};"
 | |
| 					]);
 | |
| 				}
 | |
| 				return source;
 | |
| 			}
 | |
| 		);
 | |
| 		mainTemplate.hooks.requireEnsure.tap(
 | |
| 			"WebWorkerMainTemplatePlugin",
 | |
| 			(_, chunkIdExpression, { chunk, hash }) => {
 | |
| 				// TODO use chunkIdExpression instead of chunkId
 | |
| 				const chunkFilename = mainTemplate.outputOptions.chunkFilename;
 | |
| 				const chunkMaps = chunk.getChunkMaps();
 | |
| 				return Template.asString([
 | |
| 					"promises.push(Promise.resolve().then(function() {",
 | |
| 					Template.indent([
 | |
| 						'// "1" is the signal for "already loaded"',
 | |
| 						"if(!installedChunks[chunkId]) {",
 | |
| 						Template.indent([
 | |
| 							"importScripts(" +
 | |
| 								mainTemplate.getAssetPath(JSON.stringify(chunkFilename), {
 | |
| 									hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`,
 | |
| 									hashWithLength: length =>
 | |
| 										`" + ${mainTemplate.renderCurrentHashCode(
 | |
| 											hash,
 | |
| 											length
 | |
| 										)} + "`,
 | |
| 									chunk: {
 | |
| 										id: '" + chunkId + "',
 | |
| 										hash: `" + ${JSON.stringify(chunkMaps.hash)}[chunkId] + "`,
 | |
| 										hashWithLength(length) {
 | |
| 											const shortChunkHashMap = Object.create(null);
 | |
| 											for (const chunkId of Object.keys(chunkMaps.hash)) {
 | |
| 												if (typeof chunkMaps.hash[chunkId] === "string") {
 | |
| 													shortChunkHashMap[chunkId] = chunkMaps.hash[
 | |
| 														chunkId
 | |
| 													].substr(0, length);
 | |
| 												}
 | |
| 											}
 | |
| 											return `" + ${JSON.stringify(
 | |
| 												shortChunkHashMap
 | |
| 											)}[chunkId] + "`;
 | |
| 										},
 | |
| 										contentHash: {
 | |
| 											javascript: `" + ${JSON.stringify(
 | |
| 												chunkMaps.contentHash.javascript
 | |
| 											)}[chunkId] + "`
 | |
| 										},
 | |
| 										contentHashWithLength: {
 | |
| 											javascript: length => {
 | |
| 												const shortContentHashMap = {};
 | |
| 												const contentHash = chunkMaps.contentHash.javascript;
 | |
| 												for (const chunkId of Object.keys(contentHash)) {
 | |
| 													if (typeof contentHash[chunkId] === "string") {
 | |
| 														shortContentHashMap[chunkId] = contentHash[
 | |
| 															chunkId
 | |
| 														].substr(0, length);
 | |
| 													}
 | |
| 												}
 | |
| 												return `" + ${JSON.stringify(
 | |
| 													shortContentHashMap
 | |
| 												)}[chunkId] + "`;
 | |
| 											}
 | |
| 										},
 | |
| 										name: `" + (${JSON.stringify(
 | |
| 											chunkMaps.name
 | |
| 										)}[chunkId]||chunkId) + "`
 | |
| 									},
 | |
| 									contentHashType: "javascript"
 | |
| 								}) +
 | |
| 								");"
 | |
| 						]),
 | |
| 						"}"
 | |
| 					]),
 | |
| 					"}));"
 | |
| 				]);
 | |
| 			}
 | |
| 		);
 | |
| 		mainTemplate.hooks.bootstrap.tap(
 | |
| 			"WebWorkerMainTemplatePlugin",
 | |
| 			(source, renderContext) => {
 | |
| 				const { chunk } = renderContext;
 | |
| 				if (needChunkOnDemandLoadingCode(chunk)) {
 | |
| 					const chunkCallbackName =
 | |
| 						mainTemplate.outputOptions.chunkCallbackName;
 | |
| 					const globalObject = mainTemplate.outputOptions.globalObject;
 | |
| 					return Template.asString([
 | |
| 						source,
 | |
| 						`${globalObject}[${JSON.stringify(
 | |
| 							chunkCallbackName
 | |
| 						)}] = function webpackChunkCallback(chunkIds, moreModules) {`,
 | |
| 						Template.indent([
 | |
| 							"for(var moduleId in moreModules) {",
 | |
| 							Template.indent(
 | |
| 								mainTemplate.renderAddModule(
 | |
| 									"moduleId",
 | |
| 									"moreModules[moduleId]",
 | |
| 									renderContext
 | |
| 								)
 | |
| 							),
 | |
| 							"}",
 | |
| 							"while(chunkIds.length)",
 | |
| 							Template.indent("installedChunks[chunkIds.pop()] = 1;")
 | |
| 						]),
 | |
| 						"};"
 | |
| 					]);
 | |
| 				}
 | |
| 				return source;
 | |
| 			}
 | |
| 		);
 | |
| 		hotBootstrap.tap("WebWorkerMainTemplatePlugin", (source, chunk, hash) => {
 | |
| 			const hotUpdateChunkFilename =
 | |
| 				mainTemplate.outputOptions.hotUpdateChunkFilename;
 | |
| 			const hotUpdateMainFilename =
 | |
| 				mainTemplate.outputOptions.hotUpdateMainFilename;
 | |
| 			const hotUpdateFunction = mainTemplate.outputOptions.hotUpdateFunction;
 | |
| 			const globalObject = mainTemplate.outputOptions.globalObject;
 | |
| 			const currentHotUpdateChunkFilename = mainTemplate.getAssetPath(
 | |
| 				JSON.stringify(hotUpdateChunkFilename),
 | |
| 				{
 | |
| 					hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`,
 | |
| 					hashWithLength: length =>
 | |
| 						`" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`,
 | |
| 					chunk: {
 | |
| 						id: '" + chunkId + "'
 | |
| 					}
 | |
| 				}
 | |
| 			);
 | |
| 			const currentHotUpdateMainFilename = mainTemplate.getAssetPath(
 | |
| 				JSON.stringify(hotUpdateMainFilename),
 | |
| 				{
 | |
| 					hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`,
 | |
| 					hashWithLength: length =>
 | |
| 						`" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`
 | |
| 				}
 | |
| 			);
 | |
| 
 | |
| 			return (
 | |
| 				source +
 | |
| 				"\n" +
 | |
| 				`var parentHotUpdateCallback = ${globalObject}[${JSON.stringify(
 | |
| 					hotUpdateFunction
 | |
| 				)}];\n` +
 | |
| 				`${globalObject}[${JSON.stringify(hotUpdateFunction)}] = ` +
 | |
| 				Template.getFunctionContent(require("./WebWorkerMainTemplate.runtime"))
 | |
| 					.replace(/\/\/\$semicolon/g, ";")
 | |
| 					.replace(/\$hotMainFilename\$/g, currentHotUpdateMainFilename)
 | |
| 					.replace(/\$hotChunkFilename\$/g, currentHotUpdateChunkFilename)
 | |
| 					.replace(/\$hash\$/g, JSON.stringify(hash))
 | |
| 			);
 | |
| 		});
 | |
| 		mainTemplate.hooks.hash.tap("WebWorkerMainTemplatePlugin", hash => {
 | |
| 			hash.update("webworker");
 | |
| 			hash.update("4");
 | |
| 		});
 | |
| 	}
 | |
| }
 | |
| module.exports = WebWorkerMainTemplatePlugin;
 |