UNPKG

@quasar/app-vite

Version:

Quasar Framework App CLI with Vite

251 lines (209 loc) 6.03 kB
import { readFileSync, statSync } from 'node:fs' import { join, dirname, basename } from 'node:path' import { gzipSync } from 'zlib' import { underline, green, blue, magenta, cyan, gray } from 'kolorist' import { globSync } from 'tinyglobby' const highlightTypes = ['js', 'css'] const delimiters = { top: { start: ' ╔', middle: '═', end: '╗', join: '╦' }, separator: { start: ' ╟', middle: '─', end: '╢', join: '╫' }, thickSeparator: { start: ' ╠', middle: '═', end: '╣', join: '╬' }, line: { start: ' ║', middle: '─', end: '║', join: '║' }, bottom: { start: ' ╚', middle: '═', end: '╝', join: '╩' } } const colorFn = { js: green, css: blue, json: magenta, html: cyan } function getAssets(distDir) { const acc = [] Object.keys(colorFn).forEach(type => { const fileList = globSync([`**/*.${type}`], { cwd: distDir }) const assets = fileList.map(name => { const file = join(distDir, name) const { size } = statSync(file) return { name, file, size, type } }) acc.push(...assets) }) return acc } function getHumanSize(bytes) { return `${(bytes / 1024).toFixed(2)} KB` } function getGzippedSize(file) { try { const buffer = readFileSync(file) return gzipSync(buffer).length } catch { return '-' } } function getAssetLines(assetList, showGzipped) { const total = highlightTypes.reduce((acc, type) => { acc[type] = { size: 0, number: 0 } return acc }, {}) const lineList = [] let lastType = null assetList.forEach(asset => { if (lastType !== asset.type) { lastType = asset.type lineList.push('separator') } const folder = dirname(asset.name) const filename = basename(asset.name) const size = getHumanSize(asset.size) const shouldHighlight = highlightTypes.includes(asset.type) const acc = { asset: (folder !== '.' ? gray(folder + '/') : '') + colorFn[asset.type](filename), assetLen: ((folder !== '.' ? folder + '/' : '') + filename).length, size, sizeLen: size.length } if (showGzipped === true) { const val = shouldHighlight === true ? getHumanSize(getGzippedSize(asset.file)) : '-' acc.gzipped = gray(val) acc.gzippedLen = val.length } if (shouldHighlight === true) { const target = total[asset.type] target.size += asset.size target.number++ } lineList.push(acc) }) lineList.push('thickSeparator') highlightTypes.forEach(type => { const target = total[type] const plural = target.number > 1 ? 's' : '' const asset = `Total ${type.toUpperCase()} (${target.number} file${plural})` const size = getHumanSize(target.size) lineList.push({ asset: colorFn[type](asset), assetLen: asset.length, size, sizeLen: size.length, gzipped: gray('-'), gzippedLen: 1 }) }) return lineList } function getAssetColumnWidth(assetList) { const total = highlightTypes.reduce((acc, type) => { acc[type] = 0 return acc }, {}) let maxAssetNameLen = assetList.reduce((acc, asset) => { if (highlightTypes.includes(asset.type)) { total[asset.type]++ } return Math.max(acc, asset.name.length) }, 0) highlightTypes.forEach(type => { const target = total[type] const plural = target.number > 1 ? 's' : '' const banner = `Total ${type.toUpperCase()} (${target.number} file${plural})` if (banner.length > maxAssetNameLen) { maxAssetNameLen = banner.length } }) return /* spacing */ 2 + maxAssetNameLen } function capitalize(str) { return str.charAt(0).toUpperCase() + str.slice(1) } function getTable(widthMap) { const acc = {} const colKeys = Object.keys(widthMap) const separatorLine = delimiters.separator.start + colKeys .map(key => delimiters.separator.middle.repeat(widthMap[key])) .join(delimiters.separator.join) + delimiters.separator.end const thickSeparatorLine = delimiters.thickSeparator.start + colKeys .map(key => delimiters.thickSeparator.middle.repeat(widthMap[key])) .join(delimiters.thickSeparator.join) + delimiters.thickSeparator.end acc.printLine = function printLine(line) { if (line === 'separator') { console.log(separatorLine) return } if (line === 'thickSeparator') { console.log(thickSeparatorLine) return } console.log( delimiters.line.start + colKeys .map( key => ' '.repeat(widthMap[key] - line[key + 'Len'] - 1) + line[key] + ' ' ) .join(delimiters.line.join) + delimiters.line.end ) } acc.printHeader = function printHeader() { console.log( delimiters.top.start + colKeys .map(key => delimiters.top.middle.repeat(widthMap[key])) .join(delimiters.top.join) + delimiters.top.end ) acc.printLine( colKeys.reduce((localAcc, key) => { const val = capitalize(key) localAcc[key] = underline(val) localAcc[key + 'Len'] = val.length return localAcc }, {}) ) } acc.printFooter = function printFooter() { console.log( delimiters.bottom.start + colKeys .map(key => delimiters.bottom.middle.repeat(widthMap[key])) .join(delimiters.bottom.join) + delimiters.bottom.end + '\n' ) } return acc } export function printBuildSummary(distDir, showGzipped) { const assetList = getAssets(distDir) const widthMap = { asset: getAssetColumnWidth(assetList), size: 14 } if (showGzipped === true) { widthMap.gzipped = widthMap.size } const table = getTable(widthMap) console.log(' Build summary with important files:') table.printHeader() getAssetLines(assetList, showGzipped).forEach(table.printLine) table.printFooter() }