| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | /* | 
					
						
							|  |  |  | 	MIT License http://www.opensource.org/licenses/mit-license.php
 | 
					
						
							|  |  |  | 	Author Tobias Koppers @sokra | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2018-07-30 23:08:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-08 18:32:05 +08:00
										 |  |  | const createDefaultHandler = profile => { | 
					
						
							|  |  |  | 	let lineCaretPosition = 0; | 
					
						
							|  |  |  | 	let lastState; | 
					
						
							|  |  |  | 	let lastStateTime; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	const defaultHandler = (percentage, msg, ...args) => { | 
					
						
							|  |  |  | 		let state = msg; | 
					
						
							|  |  |  | 		const details = args; | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		if (percentage < 1) { | 
					
						
							| 
									
										
										
										
											2017-11-08 18:32:05 +08:00
										 |  |  | 			percentage = Math.floor(percentage * 100); | 
					
						
							|  |  |  | 			msg = `${percentage}% ${msg}`; | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 			if (percentage < 100) { | 
					
						
							| 
									
										
										
										
											2017-11-08 18:32:05 +08:00
										 |  |  | 				msg = ` ${msg}`; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 			if (percentage < 10) { | 
					
						
							| 
									
										
										
										
											2017-11-08 18:32:05 +08:00
										 |  |  | 				msg = ` ${msg}`; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 			for (let detail of details) { | 
					
						
							|  |  |  | 				if (!detail) continue; | 
					
						
							|  |  |  | 				if (detail.length > 40) { | 
					
						
							| 
									
										
										
										
											2018-03-22 17:54:18 +08:00
										 |  |  | 					detail = `…${detail.substr(detail.length - 39)}`; | 
					
						
							| 
									
										
										
										
											2017-11-08 18:32:05 +08:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				msg += ` ${detail}`; | 
					
						
							| 
									
										
										
										
											2018-01-22 20:52:43 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-11-08 18:32:05 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		if (profile) { | 
					
						
							| 
									
										
										
										
											2017-11-08 18:32:05 +08:00
										 |  |  | 			state = state.replace(/^\d+\/\d+\s+/, ""); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 			if (percentage === 0) { | 
					
						
							| 
									
										
										
										
											2017-11-08 18:32:05 +08:00
										 |  |  | 				lastState = null; | 
					
						
							|  |  |  | 				lastStateTime = Date.now(); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 			} else if (state !== lastState || percentage === 1) { | 
					
						
							| 
									
										
										
										
											2017-11-08 18:32:05 +08:00
										 |  |  | 				const now = Date.now(); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 				if (lastState) { | 
					
						
							| 
									
										
										
										
											2017-11-08 18:32:05 +08:00
										 |  |  | 					const stateMsg = `${now - lastStateTime}ms ${lastState}`; | 
					
						
							|  |  |  | 					goToLineStart(stateMsg); | 
					
						
							|  |  |  | 					process.stderr.write(stateMsg + "\n"); | 
					
						
							|  |  |  | 					lineCaretPosition = 0; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				lastState = state; | 
					
						
							|  |  |  | 				lastStateTime = now; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		goToLineStart(msg); | 
					
						
							|  |  |  | 		process.stderr.write(msg); | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	const goToLineStart = nextMessage => { | 
					
						
							|  |  |  | 		let str = ""; | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		for (; lineCaretPosition > nextMessage.length; lineCaretPosition--) { | 
					
						
							| 
									
										
										
										
											2017-11-08 18:32:05 +08:00
										 |  |  | 			str += "\b \b"; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		for (var i = 0; i < lineCaretPosition; i++) { | 
					
						
							| 
									
										
										
										
											2017-11-08 18:32:05 +08:00
										 |  |  | 			str += "\b"; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		lineCaretPosition = nextMessage.length; | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		if (str) process.stderr.write(str); | 
					
						
							| 
									
										
										
										
											2017-11-08 18:32:05 +08:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return defaultHandler; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | class ProgressPlugin { | 
					
						
							|  |  |  | 	constructor(options) { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		if (typeof options === "function") { | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 			options = { | 
					
						
							|  |  |  | 				handler: options | 
					
						
							|  |  |  | 			}; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		options = options || {}; | 
					
						
							|  |  |  | 		this.profile = options.profile; | 
					
						
							|  |  |  | 		this.handler = options.handler; | 
					
						
							| 
									
										
										
										
											2016-01-10 06:48:37 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 	apply(compiler) { | 
					
						
							| 
									
										
										
										
											2017-11-08 18:32:05 +08:00
										 |  |  | 		const handler = this.handler || createDefaultHandler(this.profile); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		if (compiler.compilers) { | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 			const states = new Array(compiler.compilers.length); | 
					
						
							| 
									
										
										
										
											2017-11-08 18:32:05 +08:00
										 |  |  | 			compiler.compilers.forEach((compiler, idx) => { | 
					
						
							| 
									
										
										
										
											2017-12-20 16:53:33 +08:00
										 |  |  | 				new ProgressPlugin((p, msg, ...args) => { | 
					
						
							| 
									
										
										
										
											2018-05-12 01:06:10 +08:00
										 |  |  | 					states[idx] = [p, msg, ...args]; | 
					
						
							| 
									
										
										
										
											2017-11-08 18:32:05 +08:00
										 |  |  | 					handler( | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 						states | 
					
						
							|  |  |  | 							.map(state => (state && state[0]) || 0) | 
					
						
							|  |  |  | 							.reduce((a, b) => a + b) / states.length, | 
					
						
							| 
									
										
										
										
											2017-11-08 18:32:05 +08:00
										 |  |  | 						`[${idx}] ${msg}`, | 
					
						
							|  |  |  | 						...args | 
					
						
							|  |  |  | 					); | 
					
						
							| 
									
										
										
										
											2017-12-20 16:53:33 +08:00
										 |  |  | 				}).apply(compiler); | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 			}); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			let lastModulesCount = 0; | 
					
						
							|  |  |  | 			let moduleCount = 500; | 
					
						
							|  |  |  | 			let doneModules = 0; | 
					
						
							|  |  |  | 			const activeModules = []; | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-08 18:32:05 +08:00
										 |  |  | 			const update = module => { | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 				handler( | 
					
						
							| 
									
										
										
										
											2018-05-29 22:14:16 +08:00
										 |  |  | 					0.1 + (doneModules / Math.max(lastModulesCount, moduleCount)) * 0.6, | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 					"building modules", | 
					
						
							|  |  |  | 					`${doneModules}/${moduleCount} modules`, | 
					
						
							| 
									
										
										
										
											2017-02-22 16:12:24 +08:00
										 |  |  | 					`${activeModules.length} active`, | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 					activeModules[activeModules.length - 1] | 
					
						
							|  |  |  | 				); | 
					
						
							|  |  |  | 			}; | 
					
						
							| 
									
										
										
										
											2015-11-22 05:59:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-08 18:32:05 +08:00
										 |  |  | 			const moduleDone = module => { | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 				doneModules++; | 
					
						
							|  |  |  | 				const ident = module.identifier(); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 				if (ident) { | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 					const idx = activeModules.indexOf(ident); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					if (idx >= 0) activeModules.splice(idx, 1); | 
					
						
							| 
									
										
										
										
											2015-11-22 05:59:08 +08:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2014-06-19 05:02:33 +08:00
										 |  |  | 				update(); | 
					
						
							| 
									
										
										
										
											2015-11-22 05:59:08 +08:00
										 |  |  | 			}; | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 			compiler.hooks.compilation.tap("ProgressPlugin", compilation => { | 
					
						
							|  |  |  | 				if (compilation.compiler.isChild()) return; | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 				lastModulesCount = moduleCount; | 
					
						
							|  |  |  | 				moduleCount = 0; | 
					
						
							|  |  |  | 				doneModules = 0; | 
					
						
							|  |  |  | 				handler(0, "compiling"); | 
					
						
							| 
									
										
										
										
											2017-12-06 22:01:25 +08:00
										 |  |  | 				compilation.hooks.buildModule.tap("ProgressPlugin", module => { | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 					moduleCount++; | 
					
						
							|  |  |  | 					const ident = module.identifier(); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					if (ident) { | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 						activeModules.push(ident); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					update(); | 
					
						
							|  |  |  | 				}); | 
					
						
							| 
									
										
										
										
											2017-12-06 22:01:25 +08:00
										 |  |  | 				compilation.hooks.failedModule.tap("ProgressPlugin", moduleDone); | 
					
						
							|  |  |  | 				compilation.hooks.succeedModule.tap("ProgressPlugin", moduleDone); | 
					
						
							|  |  |  | 				const hooks = { | 
					
						
							| 
									
										
										
										
											2017-12-12 21:44:26 +08:00
										 |  |  | 					finishModules: "finish module graph", | 
					
						
							|  |  |  | 					seal: "sealing", | 
					
						
							|  |  |  | 					optimizeDependencies: "dependencies optimization", | 
					
						
							|  |  |  | 					afterOptimizeDependencies: "after dependencies optimization", | 
					
						
							|  |  |  | 					optimize: "optimizing", | 
					
						
							|  |  |  | 					optimizeModules: "module optimization", | 
					
						
							|  |  |  | 					afterOptimizeModules: "after module optimization", | 
					
						
							|  |  |  | 					optimizeChunks: "chunk optimization", | 
					
						
							|  |  |  | 					afterOptimizeChunks: "after chunk optimization", | 
					
						
							|  |  |  | 					optimizeTree: "module and chunk tree optimization", | 
					
						
							|  |  |  | 					afterOptimizeTree: "after module and chunk tree optimization", | 
					
						
							|  |  |  | 					optimizeChunkModules: "chunk modules optimization", | 
					
						
							|  |  |  | 					afterOptimizeChunkModules: "after chunk modules optimization", | 
					
						
							|  |  |  | 					reviveModules: "module reviving", | 
					
						
							|  |  |  | 					optimizeModuleOrder: "module order optimization", | 
					
						
							|  |  |  | 					advancedOptimizeModuleOrder: "advanced module order optimization", | 
					
						
							|  |  |  | 					beforeModuleIds: "before module ids", | 
					
						
							|  |  |  | 					moduleIds: "module ids", | 
					
						
							|  |  |  | 					optimizeModuleIds: "module id optimization", | 
					
						
							|  |  |  | 					afterOptimizeModuleIds: "module id optimization", | 
					
						
							|  |  |  | 					reviveChunks: "chunk reviving", | 
					
						
							|  |  |  | 					optimizeChunkOrder: "chunk order optimization", | 
					
						
							|  |  |  | 					beforeChunkIds: "before chunk ids", | 
					
						
							|  |  |  | 					optimizeChunkIds: "chunk id optimization", | 
					
						
							|  |  |  | 					afterOptimizeChunkIds: "after chunk id optimization", | 
					
						
							|  |  |  | 					recordModules: "record modules", | 
					
						
							|  |  |  | 					recordChunks: "record chunks", | 
					
						
							|  |  |  | 					beforeHash: "hashing", | 
					
						
							|  |  |  | 					afterHash: "after hashing", | 
					
						
							|  |  |  | 					recordHash: "record hash", | 
					
						
							|  |  |  | 					beforeModuleAssets: "module assets processing", | 
					
						
							|  |  |  | 					beforeChunkAssets: "chunk assets processing", | 
					
						
							|  |  |  | 					additionalChunkAssets: "additional chunk assets processing", | 
					
						
							|  |  |  | 					record: "recording", | 
					
						
							|  |  |  | 					additionalAssets: "additional asset processing", | 
					
						
							|  |  |  | 					optimizeChunkAssets: "chunk asset optimization", | 
					
						
							|  |  |  | 					afterOptimizeChunkAssets: "after chunk asset optimization", | 
					
						
							|  |  |  | 					optimizeAssets: "asset optimization", | 
					
						
							|  |  |  | 					afterOptimizeAssets: "after asset optimization", | 
					
						
							|  |  |  | 					afterSeal: "after seal" | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 				}; | 
					
						
							| 
									
										
										
										
											2017-12-12 21:44:26 +08:00
										 |  |  | 				const numberOfHooks = Object.keys(hooks).length; | 
					
						
							|  |  |  | 				Object.keys(hooks).forEach((name, idx) => { | 
					
						
							|  |  |  | 					const title = hooks[name]; | 
					
						
							| 
									
										
										
										
											2018-05-29 22:14:16 +08:00
										 |  |  | 					const percentage = (idx / numberOfHooks) * 0.25 + 0.7; | 
					
						
							| 
									
										
										
										
											2017-12-12 21:44:26 +08:00
										 |  |  | 					compilation.hooks[name].intercept({ | 
					
						
							|  |  |  | 						name: "ProgressPlugin", | 
					
						
							|  |  |  | 						context: true, | 
					
						
							|  |  |  | 						call: () => { | 
					
						
							| 
									
										
										
										
											2017-12-13 17:09:35 +08:00
										 |  |  | 							handler(percentage, title); | 
					
						
							| 
									
										
										
										
											2017-12-12 21:44:26 +08:00
										 |  |  | 						}, | 
					
						
							|  |  |  | 						tap: (context, tap) => { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 							if (context) { | 
					
						
							| 
									
										
										
										
											2017-12-13 17:09:35 +08:00
										 |  |  | 								// p is percentage from 0 to 1
 | 
					
						
							|  |  |  | 								// args is any number of messages in a hierarchical matter
 | 
					
						
							|  |  |  | 								context.reportProgress = (p, ...args) => { | 
					
						
							|  |  |  | 									handler(percentage, title, tap.name, ...args); | 
					
						
							| 
									
										
										
										
											2017-12-12 21:44:26 +08:00
										 |  |  | 								}; | 
					
						
							|  |  |  | 							} | 
					
						
							| 
									
										
										
										
											2017-12-13 17:09:35 +08:00
										 |  |  | 							handler(percentage, title, tap.name); | 
					
						
							| 
									
										
										
										
											2017-12-12 21:44:26 +08:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 					}); | 
					
						
							|  |  |  | 				}); | 
					
						
							| 
									
										
										
										
											2015-02-05 06:20:36 +08:00
										 |  |  | 			}); | 
					
						
							| 
									
										
										
										
											2017-12-12 21:44:26 +08:00
										 |  |  | 			compiler.hooks.emit.intercept({ | 
					
						
							|  |  |  | 				name: "ProgressPlugin", | 
					
						
							|  |  |  | 				context: true, | 
					
						
							|  |  |  | 				call: () => { | 
					
						
							|  |  |  | 					handler(0.95, "emitting"); | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				tap: (context, tap) => { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					if (context) { | 
					
						
							| 
									
										
										
										
											2017-12-13 17:09:35 +08:00
										 |  |  | 						context.reportProgress = (p, ...args) => { | 
					
						
							| 
									
										
										
										
											2017-12-12 21:44:26 +08:00
										 |  |  | 							handler(0.95, "emitting", tap.name, ...args); | 
					
						
							|  |  |  | 						}; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					handler(0.95, "emitting", tap.name); | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2014-06-19 05:02:33 +08:00
										 |  |  | 			}); | 
					
						
							| 
									
										
										
										
											2018-05-30 02:22:12 +08:00
										 |  |  | 			compiler.hooks.afterEmit.intercept({ | 
					
						
							|  |  |  | 				name: "ProgressPlugin", | 
					
						
							|  |  |  | 				context: true, | 
					
						
							|  |  |  | 				call: () => { | 
					
						
							|  |  |  | 					handler(0.98, "after emitting"); | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				tap: (context, tap) => { | 
					
						
							|  |  |  | 					if (context) { | 
					
						
							|  |  |  | 						context.reportProgress = (p, ...args) => { | 
					
						
							|  |  |  | 							handler(0.98, "after emitting", tap.name, ...args); | 
					
						
							|  |  |  | 						}; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					handler(0.98, "after emitting", tap.name); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}); | 
					
						
							| 
									
										
										
										
											2017-12-06 22:01:25 +08:00
										 |  |  | 			compiler.hooks.done.tap("ProgressPlugin", () => { | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 				handler(1, ""); | 
					
						
							| 
									
										
										
										
											2014-06-19 05:02:33 +08:00
										 |  |  | 			}); | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-11-22 05:59:08 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | } | 
					
						
							|  |  |  | module.exports = ProgressPlugin; |