mirror of https://github.com/webpack/webpack.git
				
				
				
			add lazy compilation for entrypoints
This commit is contained in:
		
							parent
							
								
									988cf8d47a
								
							
						
					
					
						commit
						100317556e
					
				|  | @ -1042,7 +1042,7 @@ export interface Experiments { | ||||||
| 	 */ | 	 */ | ||||||
| 	layers?: boolean; | 	layers?: boolean; | ||||||
| 	/** | 	/** | ||||||
| 	 * Compile import()s only when they are accessed. | 	 * Compile entrypoints and import()s only when they are accessed. | ||||||
| 	 */ | 	 */ | ||||||
| 	lazyCompilation?: | 	lazyCompilation?: | ||||||
| 		| boolean | 		| boolean | ||||||
|  | @ -1064,6 +1064,10 @@ export interface Experiments { | ||||||
| 				 * A custom client. | 				 * A custom client. | ||||||
| 				 */ | 				 */ | ||||||
| 				client?: string; | 				client?: string; | ||||||
|  | 				/** | ||||||
|  | 				 * Enable/disable lazy compilation for entries. | ||||||
|  | 				 */ | ||||||
|  | 				entries?: boolean; | ||||||
| 		  }; | 		  }; | ||||||
| 	/** | 	/** | ||||||
| 	 * Allow output javascript files as module source type. | 	 * Allow output javascript files as module source type. | ||||||
|  |  | ||||||
|  | @ -10,7 +10,9 @@ module.exports = { | ||||||
| 		idleTimeout: 5000 | 		idleTimeout: 5000 | ||||||
| 	}, | 	}, | ||||||
| 	experiments: { | 	experiments: { | ||||||
| 		lazyCompilation: true | 		lazyCompilation: { | ||||||
|  | 			entries: false | ||||||
|  | 		} | ||||||
| 	}, | 	}, | ||||||
| 	devServer: { | 	devServer: { | ||||||
| 		hot: true, | 		hot: true, | ||||||
|  |  | ||||||
|  | @ -2,16 +2,12 @@ | ||||||
| 
 | 
 | ||||||
| "use strict"; | "use strict"; | ||||||
| 
 | 
 | ||||||
| if (!module.hot) { |  | ||||||
| 	throw new Error( |  | ||||||
| 		"Environment doesn't support lazy compilation (requires Hot Module Replacement enabled)" |  | ||||||
| 	); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| var urlBase = decodeURIComponent(__resourceQuery.slice(1)); | var urlBase = decodeURIComponent(__resourceQuery.slice(1)); | ||||||
| exports.keepAlive = function (options) { | exports.keepAlive = function (options) { | ||||||
| 	var data = options.data; | 	var data = options.data; | ||||||
| 	var onError = options.onError; | 	var onError = options.onError; | ||||||
|  | 	var active = options.active; | ||||||
|  | 	var module = options.module; | ||||||
| 	var response; | 	var response; | ||||||
| 	var request = require("http").request( | 	var request = require("http").request( | ||||||
| 		urlBase + data, | 		urlBase + data, | ||||||
|  | @ -22,6 +18,11 @@ exports.keepAlive = function (options) { | ||||||
| 		function (res) { | 		function (res) { | ||||||
| 			response = res; | 			response = res; | ||||||
| 			response.on("error", errorHandler); | 			response.on("error", errorHandler); | ||||||
|  | 			if (!active && !module.hot) { | ||||||
|  | 				console.log( | ||||||
|  | 					"Hot Module Replacement is not enabled. Waiting for process restart..." | ||||||
|  | 				); | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 	); | 	); | ||||||
| 	function errorHandler(err) { | 	function errorHandler(err) { | ||||||
|  |  | ||||||
|  | @ -2,9 +2,9 @@ | ||||||
| 
 | 
 | ||||||
| "use strict"; | "use strict"; | ||||||
| 
 | 
 | ||||||
| if (typeof EventSource !== "function" || !module.hot) { | if (typeof EventSource !== "function") { | ||||||
| 	throw new Error( | 	throw new Error( | ||||||
| 		"Environment doesn't support lazy compilation (requires EventSource and Hot Module Replacement enabled)" | 		"Environment doesn't support lazy compilation (requires EventSource)" | ||||||
| 	); | 	); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -45,12 +45,19 @@ var updateEventSource = function updateEventSource() { | ||||||
| exports.keepAlive = function (options) { | exports.keepAlive = function (options) { | ||||||
| 	var data = options.data; | 	var data = options.data; | ||||||
| 	var onError = options.onError; | 	var onError = options.onError; | ||||||
|  | 	var active = options.active; | ||||||
|  | 	var module = options.module; | ||||||
| 	errorHandlers.add(onError); | 	errorHandlers.add(onError); | ||||||
| 	var value = activeKeys.get(data) || 0; | 	var value = activeKeys.get(data) || 0; | ||||||
| 	activeKeys.set(data, value + 1); | 	activeKeys.set(data, value + 1); | ||||||
| 	if (value === 0) { | 	if (value === 0) { | ||||||
| 		updateEventSource(); | 		updateEventSource(); | ||||||
| 	} | 	} | ||||||
|  | 	if (!active && !module.hot) { | ||||||
|  | 		console.log( | ||||||
|  | 			"Hot Module Replacement is not enabled. Waiting for process restart..." | ||||||
|  | 		); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	return function () { | 	return function () { | ||||||
| 		errorHandlers.delete(onError); | 		errorHandlers.delete(onError); | ||||||
|  |  | ||||||
|  | @ -256,7 +256,10 @@ class WebpackOptionsApply extends OptionsApply { | ||||||
| 						options.experiments.lazyCompilation.client) || | 						options.experiments.lazyCompilation.client) || | ||||||
| 					`webpack/hot/lazy-compilation-${ | 					`webpack/hot/lazy-compilation-${ | ||||||
| 						options.externalsPresets.node ? "node" : "web" | 						options.externalsPresets.node ? "node" : "web" | ||||||
| 					}.js` | 					}.js`,
 | ||||||
|  | 				entries: | ||||||
|  | 					typeof options.experiments.lazyCompilation !== "object" || | ||||||
|  | 					options.experiments.lazyCompilation.entries !== false | ||||||
| 			}).apply(compiler); | 			}).apply(compiler); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -59,12 +59,8 @@ class LazyCompilationDependency extends Dependency { | ||||||
| registerNotSerializable(LazyCompilationDependency); | registerNotSerializable(LazyCompilationDependency); | ||||||
| 
 | 
 | ||||||
| class LazyCompilationProxyModule extends Module { | class LazyCompilationProxyModule extends Module { | ||||||
| 	constructor(originalModule, request, client, data, active) { | 	constructor(context, originalModule, request, client, data, active) { | ||||||
| 		super( | 		super("lazy-compilation-proxy", context, originalModule.layer); | ||||||
| 			"lazy-compilation-proxy", |  | ||||||
| 			originalModule.context, |  | ||||||
| 			originalModule.layer |  | ||||||
| 		); |  | ||||||
| 		this.originalModule = originalModule; | 		this.originalModule = originalModule; | ||||||
| 		this.request = request; | 		this.request = request; | ||||||
| 		this.client = client; | 		this.client = client; | ||||||
|  | @ -172,14 +168,16 @@ class LazyCompilationProxyModule extends Module { | ||||||
| 			.dependencies[0]); | 			.dependencies[0]); | ||||||
| 		const clientModule = moduleGraph.getModule(clientDep); | 		const clientModule = moduleGraph.getModule(clientDep); | ||||||
| 		const block = this.blocks[0]; | 		const block = this.blocks[0]; | ||||||
| 		const keepActive = Template.asString([ | 		const client = Template.asString([ | ||||||
| 			`var client = ${runtimeTemplate.moduleExports({ | 			`var client = ${runtimeTemplate.moduleExports({ | ||||||
| 				module: clientModule, | 				module: clientModule, | ||||||
| 				chunkGraph, | 				chunkGraph, | ||||||
| 				request: clientDep.userRequest, | 				request: clientDep.userRequest, | ||||||
| 				runtimeRequirements | 				runtimeRequirements | ||||||
| 			})}`,
 | 			})}`,
 | ||||||
| 			`var data = ${JSON.stringify(this.data)};`, | 			`var data = ${JSON.stringify(this.data)};` | ||||||
|  | 		]); | ||||||
|  | 		const keepActive = Template.asString([ | ||||||
| 			`var dispose = client.keepAlive({ data, active: ${JSON.stringify( | 			`var dispose = client.keepAlive({ data, active: ${JSON.stringify( | ||||||
| 				!!block | 				!!block | ||||||
| 			)}, module, onError });` | 			)}, module, onError });` | ||||||
|  | @ -189,11 +187,7 @@ class LazyCompilationProxyModule extends Module { | ||||||
| 			const dep = block.dependencies[0]; | 			const dep = block.dependencies[0]; | ||||||
| 			const module = moduleGraph.getModule(dep); | 			const module = moduleGraph.getModule(dep); | ||||||
| 			source = Template.asString([ | 			source = Template.asString([ | ||||||
| 				"module.hot.accept();", | 				client, | ||||||
| 				`module.hot.accept(${JSON.stringify( |  | ||||||
| 					chunkGraph.getModuleId(module) |  | ||||||
| 				)}, function() { module.hot.invalidate(); });`,
 |  | ||||||
| 				"module.hot.dispose(function(data) { delete data.resolveSelf; dispose(data); });", |  | ||||||
| 				`module.exports = ${runtimeTemplate.moduleNamespacePromise({ | 				`module.exports = ${runtimeTemplate.moduleNamespacePromise({ | ||||||
| 					chunkGraph, | 					chunkGraph, | ||||||
| 					block, | 					block, | ||||||
|  | @ -203,17 +197,31 @@ class LazyCompilationProxyModule extends Module { | ||||||
| 					message: "import()", | 					message: "import()", | ||||||
| 					runtimeRequirements | 					runtimeRequirements | ||||||
| 				})};`,
 | 				})};`,
 | ||||||
| 				"if (module.hot.data && module.hot.data.resolveSelf) module.hot.data.resolveSelf(module.exports);", | 				"if (module.hot) {", | ||||||
|  | 				Template.indent([ | ||||||
|  | 					"module.hot.accept();", | ||||||
|  | 					`module.hot.accept(${JSON.stringify( | ||||||
|  | 						chunkGraph.getModuleId(module) | ||||||
|  | 					)}, function() { module.hot.invalidate(); });`,
 | ||||||
|  | 					"module.hot.dispose(function(data) { delete data.resolveSelf; dispose(data); });", | ||||||
|  | 					"if (module.hot.data && module.hot.data.resolveSelf) module.hot.data.resolveSelf(module.exports);" | ||||||
|  | 				]), | ||||||
|  | 				"}", | ||||||
| 				"function onError() { /* ignore */ }", | 				"function onError() { /* ignore */ }", | ||||||
| 				keepActive | 				keepActive | ||||||
| 			]); | 			]); | ||||||
| 		} else { | 		} else { | ||||||
| 			source = Template.asString([ | 			source = Template.asString([ | ||||||
| 				"module.hot.accept();", | 				client, | ||||||
| 				"var resolveSelf, onError;", | 				"var resolveSelf, onError;", | ||||||
| 				`module.exports = new Promise(function(resolve, reject) { resolveSelf = resolve; onError = reject; });`, | 				`module.exports = new Promise(function(resolve, reject) { resolveSelf = resolve; onError = reject; });`, | ||||||
| 				"if (module.hot.data && module.hot.data.resolveSelf) module.hot.data.resolveSelf(module.exports);", | 				"if (module.hot) {", | ||||||
| 				"module.hot.dispose(function(data) { data.resolveSelf = resolveSelf; dispose(data); });", | 				Template.indent([ | ||||||
|  | 					"module.hot.accept();", | ||||||
|  | 					"if (module.hot.data && module.hot.data.resolveSelf) module.hot.data.resolveSelf(module.exports);", | ||||||
|  | 					"module.hot.dispose(function(data) { data.resolveSelf = resolveSelf; dispose(data); });" | ||||||
|  | 				]), | ||||||
|  | 				"}", | ||||||
| 				keepActive | 				keepActive | ||||||
| 			]); | 			]); | ||||||
| 		} | 		} | ||||||
|  | @ -263,10 +271,12 @@ class LazyCompilationPlugin { | ||||||
| 	 * @param {Object} options options | 	 * @param {Object} options options | ||||||
| 	 * @param {(function(Compiler, string, function(Error?, any?): void): void) | function(Compiler, string): Promise<any>} options.backend the backend | 	 * @param {(function(Compiler, string, function(Error?, any?): void): void) | function(Compiler, string): Promise<any>} options.backend the backend | ||||||
| 	 * @param {string} options.client the client reference | 	 * @param {string} options.client the client reference | ||||||
|  | 	 * @param {boolean} options.entries true, when entries are lazy compiled | ||||||
| 	 */ | 	 */ | ||||||
| 	constructor({ backend, client }) { | 	constructor({ backend, client, entries }) { | ||||||
| 		this.backend = backend; | 		this.backend = backend; | ||||||
| 		this.client = client; | 		this.client = client; | ||||||
|  | 		this.entries = entries; | ||||||
| 	} | 	} | ||||||
| 	/** | 	/** | ||||||
| 	 * Apply the plugin | 	 * Apply the plugin | ||||||
|  | @ -292,20 +302,28 @@ class LazyCompilationPlugin { | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		); | 		); | ||||||
| 		compiler.hooks.compilation.tap( | 		compiler.hooks.thisCompilation.tap( | ||||||
| 			"LazyCompilationPlugin", | 			"LazyCompilationPlugin", | ||||||
| 			(compilation, { normalModuleFactory }) => { | 			(compilation, { normalModuleFactory }) => { | ||||||
| 				normalModuleFactory.hooks.module.tap( | 				normalModuleFactory.hooks.module.tap( | ||||||
| 					"LazyCompilationPlugin", | 					"LazyCompilationPlugin", | ||||||
| 					(originalModule, createData, resolveData) => { | 					(originalModule, createData, resolveData) => { | ||||||
| 						if ( | 						if ( | ||||||
| 							resolveData.dependencies.every(dep => dep.type === "import()") | 							resolveData.dependencies.every( | ||||||
|  | 								dep => | ||||||
|  | 									dep.type === "import()" || | ||||||
|  | 									(this.entries && dep.type === "entry") | ||||||
|  | 							) && | ||||||
|  | 							!/webpack[/\\]hot[/\\]|webpack-dev-server[/\\]client/.test( | ||||||
|  | 								resolveData.request | ||||||
|  | 							) | ||||||
| 						) { | 						) { | ||||||
| 							const moduleInfo = backend.module(originalModule); | 							const moduleInfo = backend.module(originalModule); | ||||||
| 							if (!moduleInfo) return; | 							if (!moduleInfo) return; | ||||||
| 							const { client, data, active } = moduleInfo; | 							const { client, data, active } = moduleInfo; | ||||||
| 
 | 
 | ||||||
| 							return new LazyCompilationProxyModule( | 							return new LazyCompilationProxyModule( | ||||||
|  | 								compiler.context, | ||||||
| 								originalModule, | 								originalModule, | ||||||
| 								resolveData.request, | 								resolveData.request, | ||||||
| 								client, | 								client, | ||||||
|  |  | ||||||
|  | @ -582,7 +582,7 @@ | ||||||
|           "type": "boolean" |           "type": "boolean" | ||||||
|         }, |         }, | ||||||
|         "lazyCompilation": { |         "lazyCompilation": { | ||||||
|           "description": "Compile import()s only when they are accessed.", |           "description": "Compile entrypoints and import()s only when they are accessed.", | ||||||
|           "anyOf": [ |           "anyOf": [ | ||||||
|             { |             { | ||||||
|               "type": "boolean" |               "type": "boolean" | ||||||
|  | @ -599,6 +599,10 @@ | ||||||
|                 "client": { |                 "client": { | ||||||
|                   "description": "A custom client.", |                   "description": "A custom client.", | ||||||
|                   "type": "string" |                   "type": "string" | ||||||
|  |                 }, | ||||||
|  |                 "entries": { | ||||||
|  |                   "description": "Enable/disable lazy compilation for entries.", | ||||||
|  |                   "type": "boolean" | ||||||
|                 } |                 } | ||||||
|               } |               } | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -3,6 +3,8 @@ | ||||||
| /** @type {import("../../../../").Configuration} */ | /** @type {import("../../../../").Configuration} */ | ||||||
| module.exports = { | module.exports = { | ||||||
| 	experiments: { | 	experiments: { | ||||||
| 		lazyCompilation: true | 		lazyCompilation: { | ||||||
|  | 			entries: false | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -2956,7 +2956,7 @@ declare interface Experiments { | ||||||
| 	layers?: boolean; | 	layers?: boolean; | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Compile import()s only when they are accessed. | 	 * Compile entrypoints and import()s only when they are accessed. | ||||||
| 	 */ | 	 */ | ||||||
| 	lazyCompilation?: | 	lazyCompilation?: | ||||||
| 		| boolean | 		| boolean | ||||||
|  | @ -2975,6 +2975,10 @@ declare interface Experiments { | ||||||
| 				 * A custom client. | 				 * A custom client. | ||||||
| 				 */ | 				 */ | ||||||
| 				client?: string; | 				client?: string; | ||||||
|  | 				/** | ||||||
|  | 				 * Enable/disable lazy compilation for entries. | ||||||
|  | 				 */ | ||||||
|  | 				entries?: boolean; | ||||||
| 		  }; | 		  }; | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue