| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | /* | 
					
						
							|  |  |  | 	MIT License http://www.opensource.org/licenses/mit-license.php
 | 
					
						
							|  |  |  | 	Author Tobias Koppers @sokra | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ProgressPlugin { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	constructor(options) { | 
					
						
							|  |  |  | 		if(typeof options === "function") { | 
					
						
							|  |  |  | 			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) { | 
					
						
							|  |  |  | 		const handler = this.handler || defaultHandler; | 
					
						
							|  |  |  | 		const profile = this.profile; | 
					
						
							|  |  |  | 		if(compiler.compilers) { | 
					
						
							|  |  |  | 			const states = new Array(compiler.compilers.length); | 
					
						
							|  |  |  | 			compiler.compilers.forEach(function(compiler, idx) { | 
					
						
							| 
									
										
										
										
											2017-04-03 01:07:30 +08:00
										 |  |  | 				compiler.apply(new ProgressPlugin(function(p, msg) { | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 					states[idx] = Array.prototype.slice.apply(arguments); | 
					
						
							| 
									
										
										
										
											2017-02-22 16:12:24 +08:00
										 |  |  | 					handler.apply(null, [ | 
					
						
							|  |  |  | 						states.map(state => state && state[0] || 0).reduce((a, b) => a + b) / states.length, | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 						`[${idx}] ${msg}` | 
					
						
							|  |  |  | 					].concat(Array.prototype.slice.call(arguments, 2))); | 
					
						
							|  |  |  | 				})); | 
					
						
							|  |  |  | 			}); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			let lastModulesCount = 0; | 
					
						
							|  |  |  | 			let moduleCount = 500; | 
					
						
							|  |  |  | 			let doneModules = 0; | 
					
						
							|  |  |  | 			const activeModules = []; | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 			const update = function update(module) { | 
					
						
							|  |  |  | 				handler( | 
					
						
							|  |  |  | 					0.1 + (doneModules / Math.max(lastModulesCount, moduleCount)) * 0.6, | 
					
						
							|  |  |  | 					"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-02-22 15:57:56 +08:00
										 |  |  | 			const moduleDone = function moduleDone(module) { | 
					
						
							|  |  |  | 				doneModules++; | 
					
						
							|  |  |  | 				const ident = module.identifier(); | 
					
						
							| 
									
										
										
										
											2015-11-22 05:59:08 +08:00
										 |  |  | 				if(ident) { | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 					const idx = activeModules.indexOf(ident); | 
					
						
							|  |  |  | 					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
										 |  |  | 			}; | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 			compiler.plugin("compilation", function(compilation) { | 
					
						
							|  |  |  | 				if(compilation.compiler.isChild()) return; | 
					
						
							|  |  |  | 				lastModulesCount = moduleCount; | 
					
						
							|  |  |  | 				moduleCount = 0; | 
					
						
							|  |  |  | 				doneModules = 0; | 
					
						
							|  |  |  | 				handler(0, "compiling"); | 
					
						
							|  |  |  | 				compilation.plugin("build-module", function(module) { | 
					
						
							|  |  |  | 					moduleCount++; | 
					
						
							|  |  |  | 					const ident = module.identifier(); | 
					
						
							|  |  |  | 					if(ident) { | 
					
						
							|  |  |  | 						activeModules.push(ident); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					update(); | 
					
						
							|  |  |  | 				}); | 
					
						
							|  |  |  | 				compilation.plugin("failed-module", moduleDone); | 
					
						
							|  |  |  | 				compilation.plugin("succeed-module", moduleDone); | 
					
						
							|  |  |  | 				const syncHooks = { | 
					
						
							|  |  |  | 					"seal": [0.71, "sealing"], | 
					
						
							|  |  |  | 					"optimize": [0.72, "optimizing"], | 
					
						
							|  |  |  | 					"optimize-modules-basic": [0.73, "basic module optimization"], | 
					
						
							|  |  |  | 					"optimize-modules": [0.74, "module optimization"], | 
					
						
							|  |  |  | 					"optimize-modules-advanced": [0.75, "advanced module optimization"], | 
					
						
							|  |  |  | 					"optimize-chunks-basic": [0.76, "basic chunk optimization"], | 
					
						
							|  |  |  | 					"optimize-chunks": [0.77, "chunk optimization"], | 
					
						
							|  |  |  | 					"optimize-chunks-advanced": [0.78, "advanced chunk optimization"], | 
					
						
							|  |  |  | 					// optimize-tree
 | 
					
						
							| 
									
										
										
										
											2017-05-28 23:19:48 +08:00
										 |  |  | 					"optimize-chunk-modules": [0.80, "chunk modules optimization"], | 
					
						
							|  |  |  | 					"optimize-chunk-modules-advanced": [0.81, "advanced chunk modules optimization"], | 
					
						
							|  |  |  | 					"revive-modules": [0.82, "module reviving"], | 
					
						
							|  |  |  | 					"optimize-module-order": [0.83, "module order optimization"], | 
					
						
							|  |  |  | 					"optimize-module-ids": [0.84, "module id optimization"], | 
					
						
							|  |  |  | 					"revive-chunks": [0.85, "chunk reviving"], | 
					
						
							|  |  |  | 					"optimize-chunk-order": [0.86, "chunk order optimization"], | 
					
						
							|  |  |  | 					"optimize-chunk-ids": [0.87, "chunk id optimization"], | 
					
						
							|  |  |  | 					"before-hash": [0.88, "hashing"], | 
					
						
							|  |  |  | 					"before-module-assets": [0.89, "module assets processing"], | 
					
						
							|  |  |  | 					"before-chunk-assets": [0.90, "chunk assets processing"], | 
					
						
							|  |  |  | 					"additional-chunk-assets": [0.91, "additional chunk assets processing"], | 
					
						
							|  |  |  | 					"record": [0.92, "recording"] | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 				}; | 
					
						
							|  |  |  | 				Object.keys(syncHooks).forEach(name => { | 
					
						
							|  |  |  | 					let pass = 0; | 
					
						
							|  |  |  | 					const settings = syncHooks[name]; | 
					
						
							|  |  |  | 					compilation.plugin(name, () => { | 
					
						
							|  |  |  | 						if(pass++ > 0) | 
					
						
							|  |  |  | 							handler(settings[0], settings[1], `pass ${pass}`); | 
					
						
							|  |  |  | 						else | 
					
						
							|  |  |  | 							handler(settings[0], settings[1]); | 
					
						
							|  |  |  | 					}); | 
					
						
							|  |  |  | 				}); | 
					
						
							|  |  |  | 				compilation.plugin("optimize-tree", (chunks, modules, callback) => { | 
					
						
							|  |  |  | 					handler(0.79, "module and chunk tree optimization"); | 
					
						
							|  |  |  | 					callback(); | 
					
						
							|  |  |  | 				}); | 
					
						
							|  |  |  | 				compilation.plugin("additional-assets", callback => { | 
					
						
							|  |  |  | 					handler(0.91, "additional asset processing"); | 
					
						
							|  |  |  | 					callback(); | 
					
						
							|  |  |  | 				}); | 
					
						
							|  |  |  | 				compilation.plugin("optimize-chunk-assets", (chunks, callback) => { | 
					
						
							|  |  |  | 					handler(0.92, "chunk asset optimization"); | 
					
						
							|  |  |  | 					callback(); | 
					
						
							|  |  |  | 				}); | 
					
						
							|  |  |  | 				compilation.plugin("optimize-assets", (assets, callback) => { | 
					
						
							|  |  |  | 					handler(0.94, "asset optimization"); | 
					
						
							|  |  |  | 					callback(); | 
					
						
							| 
									
										
										
										
											2015-11-22 05:59:08 +08:00
										 |  |  | 				}); | 
					
						
							| 
									
										
										
										
											2015-02-05 06:20:36 +08:00
										 |  |  | 			}); | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 			compiler.plugin("emit", (compilation, callback) => { | 
					
						
							|  |  |  | 				handler(0.95, "emitting"); | 
					
						
							| 
									
										
										
										
											2014-06-19 05:02:33 +08:00
										 |  |  | 				callback(); | 
					
						
							|  |  |  | 			}); | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 			compiler.plugin("done", () => { | 
					
						
							|  |  |  | 				handler(1, ""); | 
					
						
							| 
									
										
										
										
											2014-06-19 05:02:33 +08:00
										 |  |  | 			}); | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-12-09 23:10:38 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 		let lineCaretPosition = 0, | 
					
						
							|  |  |  | 			lastState, lastStateTime; | 
					
						
							| 
									
										
										
										
											2015-12-09 23:10:38 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 		function defaultHandler(percentage, msg) { | 
					
						
							|  |  |  | 			let state = msg; | 
					
						
							|  |  |  | 			const details = Array.prototype.slice.call(arguments, 2); | 
					
						
							|  |  |  | 			if(percentage < 1) { | 
					
						
							|  |  |  | 				percentage = Math.floor(percentage * 100); | 
					
						
							|  |  |  | 				msg = `${percentage}% ${msg}`; | 
					
						
							|  |  |  | 				if(percentage < 100) { | 
					
						
							|  |  |  | 					msg = ` ${msg}`; | 
					
						
							| 
									
										
										
										
											2015-11-22 05:59:08 +08:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 				if(percentage < 10) { | 
					
						
							|  |  |  | 					msg = ` ${msg}`; | 
					
						
							| 
									
										
										
										
											2015-12-09 23:10:38 +08:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 				details.forEach(detail => { | 
					
						
							|  |  |  | 					if(!detail) return; | 
					
						
							|  |  |  | 					if(detail.length > 40) { | 
					
						
							|  |  |  | 						detail = `...${detail.substr(detail.length - 37)}`; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					msg += ` ${detail}`; | 
					
						
							|  |  |  | 				}); | 
					
						
							| 
									
										
										
										
											2015-12-09 23:10:38 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 			if(profile) { | 
					
						
							|  |  |  | 				state = state.replace(/^\d+\/\d+\s+/, ""); | 
					
						
							|  |  |  | 				if(percentage === 0) { | 
					
						
							|  |  |  | 					lastState = null; | 
					
						
							| 
									
										
										
										
											2017-05-04 10:17:23 +08:00
										 |  |  | 					lastStateTime = Date.now(); | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 				} else if(state !== lastState || percentage === 1) { | 
					
						
							| 
									
										
										
										
											2017-05-04 10:17:23 +08:00
										 |  |  | 					const now = Date.now(); | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 					if(lastState) { | 
					
						
							|  |  |  | 						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); | 
					
						
							| 
									
										
										
										
											2015-12-09 23:10:38 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-11-22 05:59:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | 		function goToLineStart(nextMessage) { | 
					
						
							|  |  |  | 			let str = ""; | 
					
						
							|  |  |  | 			for(; lineCaretPosition > nextMessage.length; lineCaretPosition--) { | 
					
						
							|  |  |  | 				str += "\b \b"; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			for(var i = 0; i < lineCaretPosition; i++) { | 
					
						
							|  |  |  | 				str += "\b"; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			lineCaretPosition = nextMessage.length; | 
					
						
							|  |  |  | 			if(str) process.stderr.write(str); | 
					
						
							| 
									
										
										
										
											2015-11-22 05:59:08 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-02-22 15:57:56 +08:00
										 |  |  | } | 
					
						
							|  |  |  | module.exports = ProgressPlugin; |