diff --git a/snowpack/src/commands/paint.ts b/snowpack/src/commands/paint.ts index 83cea89266..2a458511a8 100644 --- a/snowpack/src/commands/paint.ts +++ b/snowpack/src/commands/paint.ts @@ -3,10 +3,30 @@ import {EventEmitter} from 'events'; import * as colors from 'kleur/colors'; import path from 'path'; import readline from 'readline'; -import {logger} from '../logger'; +import {logger, LogRecord} from '../logger'; const cwd = process.cwd(); +const IS_FILE_CHANGED_MESSAGE = /File changed\.\.\./; +/** Convert a logger's history into the proper dev console format. */ +function summarizeHistory(history: readonly LogRecord[]): string { + // Note: history array can get long over time. Performance matters here! + return history.reduce((historyString, record) => { + let line; + // We want to summarize common repeat "file changed" events to reduce noise. + // All other logs should be included verbatim, with all repeats added. + if (record.count === 1) { + line = record.val; + } else if (IS_FILE_CHANGED_MESSAGE.test(record.val)) { + line = record.val + colors.green(` [x${record.count}]`); + } else { + line = Array(record.count).fill(record.val).join('\n'); + } + // Note: this includes an extra '\n' character at the start. + // Fine for our use-case, but be aware. + return historyString + '\n' + line; + }, ''); +} export const paintEvent = { BUILD_FILE: 'BUILD_FILE', LOAD_ERROR: 'LOAD_ERROR', @@ -112,8 +132,8 @@ export function paint(bus: EventEmitter, plugins: string[]) { // Console Output const history = logger.getHistory(); if (history.length) { - process.stdout.write(`${colors.underline(colors.bold('▼ Console'))}\n\n`); - process.stdout.write(history.join('\n')); + process.stdout.write(`${colors.underline(colors.bold('▼ Console'))}\n`); + process.stdout.write(summarizeHistory(history)); process.stdout.write('\n\n'); } // Worker Dashboards diff --git a/snowpack/src/logger.ts b/snowpack/src/logger.ts index 47da4fa08e..2db785d865 100644 --- a/snowpack/src/logger.ts +++ b/snowpack/src/logger.ts @@ -1,6 +1,11 @@ import * as colors from 'kleur/colors'; import {LoggerLevel, LoggerEvent, LoggerOptions} from './types/snowpack'; +export interface LogRecord { + val: string; + count: number; +} + const levels: Record = { debug: 20, info: 30, @@ -16,7 +21,7 @@ class SnowpackLogger { /** configure maximum number of logs to keep (default: 500) */ public logCount = 500; - private history: string[] = []; // this is immutable; must be accessed with Logger.getHistory() + private history: {val: string; count: number}[] = []; // this is immutable; must be accessed with Logger.getHistory() private callbacks: Record void> = { debug: (message: string) => { console.log(message); @@ -45,7 +50,12 @@ class SnowpackLogger { const log = `${colors.dim(`[${name}]`)} ${text}`; // add to log history and remove old logs to keep memory low - this.history.push(log); + const lastHistoryItem = this.history[this.history.length - 1]; + if (lastHistoryItem && lastHistoryItem.val === log) { + lastHistoryItem.count++; + } else { + this.history.push({val: log, count: 1}); + } while (this.history.length > this.logCount) { this.history.shift(); } @@ -83,7 +93,7 @@ class SnowpackLogger { } /** get full logging history */ - public getHistory(): ReadonlyArray { + public getHistory(): ReadonlyArray { return this.history; }