@angular-devkit/build-angular
Version:
Angular Webpack Build Facade
227 lines (223 loc) • 8.75 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.createWebpackLoggingCallback = exports.statsHasWarnings = exports.statsHasErrors = exports.statsErrorsToString = exports.statsWarningsToString = exports.statsToString = exports.generateBuildStats = exports.generateBuildStatsTable = exports.generateBundleStats = exports.formatSize = void 0;
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
// tslint:disable
// TODO: cleanup this file, it's copied as is from Angular CLI.
const core_1 = require("@angular-devkit/core");
const path = require("path");
const textTable = require("text-table");
const color_1 = require("../../utils/color");
function formatSize(size) {
if (size <= 0) {
return '0 bytes';
}
const abbreviations = ['bytes', 'kB', 'MB', 'GB'];
const index = Math.floor(Math.log(size) / Math.log(1024));
return `${+(size / Math.pow(1024, index)).toPrecision(3)} ${abbreviations[index]}`;
}
exports.formatSize = formatSize;
;
function generateBundleStats(info, colors) {
var _a;
const g = (x) => (colors ? color_1.colors.greenBright(x) : x);
const c = (x) => (colors ? color_1.colors.cyanBright(x) : x);
const size = typeof info.size === 'number' ? formatSize(info.size) : '-';
const files = info.files.filter(f => !f.endsWith('.map')).map(f => path.basename(f)).join(', ');
const names = ((_a = info.names) === null || _a === void 0 ? void 0 : _a.length) ? info.names.join(', ') : '-';
const initial = !!(info.entry || info.initial);
return {
initial,
stats: [g(files), names, c(size)],
};
}
exports.generateBundleStats = generateBundleStats;
function generateBuildStatsTable(data, colors) {
const changedEntryChunksStats = [];
const changedLazyChunksStats = [];
for (const { initial, stats } of data) {
if (initial) {
changedEntryChunksStats.push(stats);
}
else {
changedLazyChunksStats.push(stats);
}
}
const bundleInfo = [];
const bold = (x) => colors ? color_1.colors.bold(x) : x;
const dim = (x) => colors ? color_1.colors.dim(x) : x;
// Entry chunks
if (changedEntryChunksStats.length) {
bundleInfo.push(['Initial Chunk Files', 'Names', 'Size'].map(bold), ...changedEntryChunksStats);
}
// Seperator
if (changedEntryChunksStats.length && changedLazyChunksStats.length) {
bundleInfo.push([]);
}
// Lazy chunks
if (changedLazyChunksStats.length) {
bundleInfo.push(['Lazy Chunk Files', 'Names', 'Size'].map(bold), ...changedLazyChunksStats);
}
return textTable(bundleInfo, {
hsep: dim(' | '),
stringLength: s => color_1.removeColor(s).length,
});
}
exports.generateBuildStatsTable = generateBuildStatsTable;
function generateBuildStats(hash, time, colors) {
const w = (x) => colors ? color_1.colors.bold.white(x) : x;
return `Build at: ${w(new Date().toISOString())} - Hash: ${w(hash)} - Time: ${w('' + time)}ms`;
}
exports.generateBuildStats = generateBuildStats;
function statsToString(json, statsConfig) {
const colors = statsConfig.colors;
const rs = (x) => colors ? color_1.colors.reset(x) : x;
const changedChunksStats = [];
for (const chunk of json.chunks) {
if (!chunk.rendered) {
continue;
}
const assets = json.assets.filter((asset) => chunk.files.includes(asset.name));
const summedSize = assets.filter((asset) => !asset.name.endsWith(".map")).reduce((total, asset) => { return total + asset.size; }, 0);
changedChunksStats.push(generateBundleStats({ ...chunk, size: summedSize }, colors));
}
const unchangedChunkNumber = json.chunks.length - changedChunksStats.length;
const statsTable = generateBuildStatsTable(changedChunksStats, colors);
if (unchangedChunkNumber > 0) {
return '\n' + rs(core_1.tags.stripIndents `
${statsTable}
${unchangedChunkNumber} unchanged chunks
${generateBuildStats(json.hash, json.time, colors)}
`);
}
else {
return '\n' + rs(core_1.tags.stripIndents `
${statsTable}
${generateBuildStats(json.hash, json.time, colors)}
`);
}
}
exports.statsToString = statsToString;
const ERRONEOUS_WARNINGS_FILTER = (warning) => ![
// TODO(#16193): Don't emit this warning in the first place rather than just suppressing it.
/multiple assets emit different content.*3rdpartylicenses\.txt/i,
// Webpack 5+ has no facility to disable this warning.
// System.import is used in @angular/core for deprecated string-form lazy routes
/System.import\(\) is deprecated and will be removed soon/i,
].some(msg => msg.test(warning));
function statsWarningsToString(json, statsConfig) {
const colors = statsConfig.colors;
const c = (x) => colors ? color_1.colors.reset.cyan(x) : x;
const y = (x) => colors ? color_1.colors.reset.yellow(x) : x;
const yb = (x) => colors ? color_1.colors.reset.yellowBright(x) : x;
const warnings = [...json.warnings];
if (json.children) {
warnings.push(...json.children
.map((c) => c.warnings)
.reduce((a, b) => [...a, ...b], []));
}
let output = '';
for (const warning of warnings) {
if (typeof warning === 'string') {
if (!ERRONEOUS_WARNINGS_FILTER(warning)) {
continue;
}
output += yb(`Warning: ${warning}\n\n`);
}
else {
if (!ERRONEOUS_WARNINGS_FILTER(warning.message)) {
continue;
}
const file = warning.file || warning.moduleName;
if (file) {
output += c(file);
if (warning.loc) {
output += ':' + yb(warning.loc);
}
output += ' - ';
}
if (!/^warning/i.test(warning.message)) {
output += y('Warning: ');
}
output += `${warning.message}\n\n`;
}
}
if (output) {
return '\n' + output;
}
return '';
}
exports.statsWarningsToString = statsWarningsToString;
function statsErrorsToString(json, statsConfig) {
const colors = statsConfig.colors;
const c = (x) => colors ? color_1.colors.reset.cyan(x) : x;
const yb = (x) => colors ? color_1.colors.reset.yellowBright(x) : x;
const r = (x) => colors ? color_1.colors.reset.redBright(x) : x;
const errors = [...json.errors];
if (json.children) {
errors.push(...json.children
.map((c) => c.errors)
.reduce((a, b) => [...a, ...b], []));
}
let output = '';
for (const error of errors) {
if (typeof error === 'string') {
output += r(`Error: ${error}\n\n`);
}
else {
const file = error.file || error.moduleName;
if (file) {
output += c(file);
if (error.loc) {
output += ':' + yb(error.loc);
}
output += ' - ';
}
if (!/^error/i.test(error.message)) {
output += r('Error: ');
}
output += `${error.message}\n\n`;
}
}
if (output) {
return '\n' + output;
}
return '';
}
exports.statsErrorsToString = statsErrorsToString;
function statsHasErrors(json) {
var _a;
return json.errors.length || !!((_a = json.children) === null || _a === void 0 ? void 0 : _a.some((c) => c.errors.length));
}
exports.statsHasErrors = statsHasErrors;
function statsHasWarnings(json) {
var _a;
return json.warnings.filter(ERRONEOUS_WARNINGS_FILTER).length ||
!!((_a = json.children) === null || _a === void 0 ? void 0 : _a.some((c) => c.warnings.filter(ERRONEOUS_WARNINGS_FILTER).length));
}
exports.statsHasWarnings = statsHasWarnings;
function createWebpackLoggingCallback(verbose, logger) {
return (stats, config) => {
// config.stats contains our own stats settings, added during buildWebpackConfig().
const json = stats.toJson(config.stats);
if (verbose) {
logger.info(stats.toString(config.stats));
}
else {
logger.info(statsToString(json, config.stats));
}
if (statsHasWarnings(json)) {
logger.warn(statsWarningsToString(json, config.stats));
}
if (statsHasErrors(json)) {
logger.error(statsErrorsToString(json, config.stats));
}
};
}
exports.createWebpackLoggingCallback = createWebpackLoggingCallback;