diff --git a/packager/react-packager/src/Server/index.js b/packager/react-packager/src/Server/index.js index b6bd9d362c443b..956986d2213c61 100644 --- a/packager/react-packager/src/Server/index.js +++ b/packager/react-packager/src/Server/index.js @@ -696,22 +696,14 @@ class Server { entry_point: options.entryFile, })), ['bundle_url']); - let consoleProgress = () => {}; + let updateTTYProgressMessage = () => {}; if (process.stdout.isTTY && !this._opts.silent) { - const onProgress = (doneCount, totalCount) => { - const format = 'transformed %s/%s (%s%)'; - const percent = Math.floor(100 * doneCount / totalCount); - terminal.status(format, doneCount, totalCount, percent); - if (doneCount === totalCount) { - terminal.persistStatus(); - } - }; - consoleProgress = throttle(onProgress, 200); + updateTTYProgressMessage = startTTYProgressMessage(); } const mres = MultipartResponse.wrap(req, res); options.onProgress = (done, total) => { - consoleProgress(done, total); + updateTTYProgressMessage(done, total); mres.writeChunk({'Content-Type': 'application/json'}, JSON.stringify({done, total})); }; @@ -893,7 +885,7 @@ class Server { entryModuleOnly: boolean, generateSourceMaps: boolean, assetPlugins: Array, - onProgress?: () => mixed, + onProgress?: (doneCont: number, totalCount: number) => mixed, } { // `true` to parse the query param as an object. const urlObj = url.parse(reqUrl, true); @@ -958,6 +950,41 @@ class Server { } } +function getProgressBar(ratio: number, length: number) { + const blockCount = Math.floor(ratio * length); + return ( + '\u2593'.repeat(blockCount) + + '\u2591'.repeat(length - blockCount) + ); +} + +/** + * We use Math.pow(ratio, 2) to as a conservative measure of progress because we + * know the `totalCount` is going to progressively increase as well. We also + * prevent the ratio from going backwards. + */ +function startTTYProgressMessage( +): (doneCount: number, totalCount: number) => void { + let currentRatio = 0; + const updateMessage = (doneCount, totalCount) => { + const isDone = doneCount === totalCount; + const conservativeRatio = Math.pow(doneCount / totalCount, 2); + currentRatio = Math.max(conservativeRatio, currentRatio); + terminal.status( + 'Transforming files %s%s% (%s/%s)%s', + isDone ? '' : getProgressBar(currentRatio, 20) + ' ', + (100 * currentRatio).toFixed(1), + doneCount, + totalCount, + isDone ? ', done.' : '...', + ); + if (isDone) { + terminal.persistStatus(); + } + }; + return throttle(updateMessage, 200); +} + function contentsEqual(array: Array, set: Set): boolean { return array.length === set.size && array.every(set.has, set); }