140 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			140 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| let chalk = require('chalk')
 | |
| let ProgressPlugin = require('webpack/lib/ProgressPlugin')
 | |
| let log = require('log-update')
 | |
| let path = require('path')
 | |
| 
 | |
| const thresholder = 0.99
 | |
| 
 | |
| function now() {
 | |
|   return new Date().toTimeString().split(' ')[0]
 | |
| }
 | |
| 
 | |
| function isEqual(arr1, arr2) {
 | |
|   let equal = arr1.length === arr2.length
 | |
|   for (let i = 0; i < arr1.length; i++) {
 | |
|     if (arr1[i] !== arr2[i]) {
 | |
|       equal = false
 | |
|       break
 | |
|     }
 | |
|   }
 | |
|   return equal
 | |
| }
 | |
| 
 | |
| class Progress {
 | |
|   constructor(options) {
 | |
|     this.delegate = new ProgressPlugin(options)
 | |
|   }
 | |
|   apply(compiler) {
 | |
|     this.delegate.apply(compiler)
 | |
|     let invalid = () => {
 | |
|       console.log(chalk.white('Compiling...'))
 | |
|     }
 | |
|     if (compiler.hooks) {
 | |
|       compiler.hooks.invalid.tap('ProgressWebpckPlugin', invalid)
 | |
|     } else {
 | |
|       compiler.plugin('invalid', invalid)
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| function progressPlugin(options = {}) {
 | |
|   let identifier = options.identifier || ''
 | |
|   let id = identifier && identifier + ' '
 | |
|   let onStart = options.onStart || (() => {})
 | |
|   let onFinish = options.onFinish
 | |
|   let onProgress = options.onProgress
 | |
|   let coloring = onProgress === undefined
 | |
|   let clear = typeof options.clear === 'boolean' ? options.clear : true
 | |
|   let startTime
 | |
|   let finishTime
 | |
|   let duration
 | |
| 
 | |
|   let prev = {}
 | |
|   const handler = (percentage, message, ...args) => {
 | |
|     startTime = Date.now()
 | |
|     let output = []
 | |
|     if (percentage > thresholder) {
 | |
|       return
 | |
|     }
 | |
|     if (percentage === 0) onStart()
 | |
|     if (percentage > 0 && percentage < thresholder) {
 | |
|       if (message === '') return
 | |
|       if (
 | |
|         prev.percentage === percentage &&
 | |
|         prev.message === message &&
 | |
|         isEqual(prev.args, args)
 | |
|       ) {
 | |
|         return
 | |
|       }
 | |
|       prev = { percentage, message, args }
 | |
|       const banner = `[${Math.round(percentage * 100)}%] `
 | |
|       output.push(coloring ? chalk.yellow(banner) : banner)
 | |
|       output.push(
 | |
|         coloring ? chalk.white(`${message} ${id}`) : `${message} ${id}`
 | |
|       )
 | |
|       if (args.length > 0) {
 | |
|         let details = args.join(' ')
 | |
|         if (
 | |
|           /^\d+\/\d+\s{1}modules/.test(args[0]) === true &&
 | |
|           args.length === 2
 | |
|         ) {
 | |
|           const rootPath = path.resolve('.')
 | |
|           details = [args[0]].concat([args[1].replace(rootPath, '')]).join(' ')
 | |
|         }
 | |
|         if (/^import\s{1}loader/.test(args[0]) === true && args.length === 1) {
 | |
|           const matches = args[0].match(
 | |
|             /^import\s{1}loader\s{1}(.+\/node_modules\/)/
 | |
|           )
 | |
|           if (matches) {
 | |
|             details = args[0].replace(matches[1], '')
 | |
|           }
 | |
|         }
 | |
|         output.push(coloring ? chalk.grey(`(${details})`) : `(${details})`)
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     // // 5. finished
 | |
|     if (percentage === thresholder) {
 | |
|       finishTime = Date.now()
 | |
|       duration = (finishTime - startTime) / 1000
 | |
|       duration = duration.toFixed(3)
 | |
| 
 | |
|       if (typeof onFinish === 'function') {
 | |
|         onFinish(id, now(), duration)
 | |
|       } else {
 | |
|         output.push(
 | |
|           coloring
 | |
|             ? chalk.white(`Build ${id}finished at ${now()} by ${duration}s`)
 | |
|             : `Build ${id}finished at ${now()} by ${duration}s`
 | |
|         )
 | |
|       }
 | |
|     }
 | |
|     if (onProgress) {
 | |
|       if (percentage > 0 && percentage < thresholder) {
 | |
|         onProgress(output, percentage)
 | |
|       }
 | |
|     } else {
 | |
|       log(output.join(''))
 | |
|       if (percentage === thresholder) {
 | |
|         if (clear) {
 | |
|           log.clear()
 | |
|         } else {
 | |
|           log.done()
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   return new Progress({
 | |
|     handler,
 | |
|     entries: false,
 | |
|     activeModules: false,
 | |
|     modules: true,
 | |
|     modulesCount: 5000,
 | |
|     dependencies: false,
 | |
|     dependenciesCount: 10000,
 | |
|     percentBy: 'entries'
 | |
|   })
 | |
| }
 | |
| 
 | |
| module.exports = progressPlugin
 |