Add better CLI logging for dev/build (#126)
* Add better CLI logging for dev/build This adds better CLI logging for dev and build. * Fix the sorting
This commit is contained in:
parent
510e7920d2
commit
9b9bdbf4a1
3 changed files with 57 additions and 16 deletions
29
src/build.ts
29
src/build.ts
|
@ -3,11 +3,12 @@ import type { LogOptions } from './logger';
|
|||
import type { AstroRuntime, LoadResult } from './runtime';
|
||||
|
||||
import { existsSync, promises as fsPromises } from 'fs';
|
||||
import { bold, green, yellow, underline } from 'kleur/colors';
|
||||
import path from 'path';
|
||||
import cheerio from 'cheerio';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { fdir } from 'fdir';
|
||||
import { defaultLogDestination, error, info } from './logger.js';
|
||||
import { defaultLogDestination, error, info, trapWarn } from './logger.js';
|
||||
import { createRuntime } from './runtime.js';
|
||||
import { bundle, collectDynamicImports } from './build/bundle.js';
|
||||
import { generateRSS } from './build/rss.js';
|
||||
|
@ -15,6 +16,7 @@ import { generateSitemap } from './build/sitemap.js';
|
|||
import { collectStatics } from './build/static.js';
|
||||
import { canonicalURL } from './build/util.js';
|
||||
|
||||
|
||||
const { mkdir, readFile, writeFile } = fsPromises;
|
||||
|
||||
interface PageBuildOptions {
|
||||
|
@ -197,7 +199,11 @@ export async function build(astroConfig: AstroConfig): Promise<0 | 1> {
|
|||
const pages = await allPages(pageRoot);
|
||||
let builtURLs: string[] = [];
|
||||
|
||||
|
||||
try {
|
||||
info(logging , 'build', yellow('! building pages...'));
|
||||
// Vue also console.warns, this silences it.
|
||||
const release = trapWarn();
|
||||
await Promise.all(
|
||||
pages.map(async (pathname) => {
|
||||
const filepath = new URL(`file://${pathname}`);
|
||||
|
@ -222,21 +228,27 @@ export async function build(astroConfig: AstroConfig): Promise<0 | 1> {
|
|||
mergeSet(imports, await collectDynamicImports(filepath, collectImportsOptions));
|
||||
})
|
||||
);
|
||||
info(logging, 'build', green('✔'), 'pages built.');
|
||||
release();
|
||||
} catch (err) {
|
||||
error(logging, 'generate', err);
|
||||
await runtime.shutdown();
|
||||
return 1;
|
||||
}
|
||||
|
||||
info(logging, 'build', yellow('! scanning pages...'));
|
||||
for (const pathname of await allPages(componentRoot)) {
|
||||
mergeSet(imports, await collectDynamicImports(new URL(`file://${pathname}`), collectImportsOptions));
|
||||
}
|
||||
info(logging, 'build', green('✔'), 'pages scanned.');
|
||||
|
||||
if (imports.size > 0) {
|
||||
try {
|
||||
info(logging, 'build', yellow('! bundling client-side code.'));
|
||||
await bundle(imports, { dist, runtime, astroConfig });
|
||||
info(logging, 'build', green('✔'), 'bundling complete.');
|
||||
} catch (err) {
|
||||
error(logging, 'generate', err);
|
||||
error(logging, 'build', err);
|
||||
await runtime.shutdown();
|
||||
return 1;
|
||||
}
|
||||
|
@ -250,6 +262,7 @@ export async function build(astroConfig: AstroConfig): Promise<0 | 1> {
|
|||
}
|
||||
|
||||
if (existsSync(astroConfig.public)) {
|
||||
info(logging, 'build', yellow(`! copying public folder...`));
|
||||
const pub = astroConfig.public;
|
||||
const publicFiles = (await new fdir().withFullPaths().crawl(fileURLToPath(pub)).withPromise()) as string[];
|
||||
for (const filepath of publicFiles) {
|
||||
|
@ -260,16 +273,28 @@ export async function build(astroConfig: AstroConfig): Promise<0 | 1> {
|
|||
const bytes = await readFile(fileUrl);
|
||||
await writeFilep(outUrl, bytes, null);
|
||||
}
|
||||
info(logging, 'build', green('✔'), 'public folder copied.');
|
||||
}
|
||||
|
||||
// build sitemap
|
||||
if (astroConfig.buildOptions.sitemap && astroConfig.buildOptions.site) {
|
||||
info(logging, 'build', yellow('! creating a sitemap...'));
|
||||
const sitemap = generateSitemap(builtURLs.map((url) => ({ canonicalURL: canonicalURL(url, astroConfig.buildOptions.site) })));
|
||||
await writeFile(new URL('./sitemap.xml', dist), sitemap, 'utf8');
|
||||
info(logging, 'build', green('✔'), 'sitemap built.');
|
||||
} else if (astroConfig.buildOptions.sitemap) {
|
||||
info(logging, 'tip', `Set "buildOptions.site" in astro.config.mjs to generate a sitemap.xml`);
|
||||
}
|
||||
|
||||
builtURLs.sort((a, b) => a.localeCompare(b, 'en', { numeric: true }));
|
||||
info(logging, 'build', underline('Pages'));
|
||||
const lastIndex = builtURLs.length - 1;
|
||||
builtURLs.forEach((url, index) => {
|
||||
const sep = index === 0 ? '┌' : index === lastIndex ? '└' : '├';
|
||||
info(logging, null, ' ' + sep, url === '/' ? url : url + '/');
|
||||
});
|
||||
|
||||
await runtime.shutdown();
|
||||
info(logging, 'build', bold(green('▶ Build Complete!')));
|
||||
return 0;
|
||||
}
|
||||
|
|
10
src/dev.ts
10
src/dev.ts
|
@ -2,9 +2,11 @@ import type { AstroConfig } from './@types/astro';
|
|||
import type { LogOptions } from './logger.js';
|
||||
|
||||
import { logger as snowpackLogger } from 'snowpack';
|
||||
import { bold, green } from 'kleur/colors';
|
||||
import http from 'http';
|
||||
import { relative as pathRelative } from 'path';
|
||||
import { defaultLogDestination, error, parseError } from './logger.js';
|
||||
import { performance } from 'perf_hooks';
|
||||
import { defaultLogDestination, error, info, parseError } from './logger.js';
|
||||
import { createRuntime } from './runtime.js';
|
||||
|
||||
const hostname = '127.0.0.1';
|
||||
|
@ -19,6 +21,7 @@ const logging: LogOptions = {
|
|||
|
||||
/** The primary dev action */
|
||||
export default async function dev(astroConfig: AstroConfig) {
|
||||
const startServerTime = performance.now();
|
||||
const { projectRoot } = astroConfig;
|
||||
|
||||
const runtime = await createRuntime(astroConfig, { mode: 'development', logging });
|
||||
|
@ -66,8 +69,9 @@ export default async function dev(astroConfig: AstroConfig) {
|
|||
|
||||
const port = astroConfig.devOptions.port;
|
||||
server.listen(port, hostname, () => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Server running at http://${hostname}:${port}/`);
|
||||
const endServerTime = performance.now();
|
||||
info(logging, 'dev server', green(`Server started in ${Math.floor(endServerTime - startServerTime)}ms.`));
|
||||
info(logging, 'dev server', `${green('Local:')} http://${hostname}:${port}/`);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -15,13 +15,16 @@ export const defaultLogDestination = new Writable({
|
|||
dest = process.stdout;
|
||||
}
|
||||
let type = event.type;
|
||||
if (event.level === 'info') {
|
||||
type = bold(blue(type));
|
||||
} else if (event.level === 'error') {
|
||||
type = bold(red(type));
|
||||
if(type !== null) {
|
||||
if (event.level === 'info') {
|
||||
type = bold(blue(type));
|
||||
} else if (event.level === 'error') {
|
||||
type = bold(red(type));
|
||||
}
|
||||
|
||||
dest.write(`[${type}] `);
|
||||
}
|
||||
|
||||
dest.write(`[${type}] `);
|
||||
dest.write(utilFormat(...event.args));
|
||||
dest.write('\n');
|
||||
|
||||
|
@ -47,7 +50,7 @@ export const defaultLogOptions: LogOptions = {
|
|||
};
|
||||
|
||||
export interface LogMessage {
|
||||
type: string;
|
||||
type: string | null;
|
||||
level: LoggerLevel;
|
||||
message: string;
|
||||
args: Array<any>;
|
||||
|
@ -62,7 +65,7 @@ const levels: Record<LoggerLevel, number> = {
|
|||
};
|
||||
|
||||
/** Full logging API */
|
||||
export function log(opts: LogOptions = defaultLogOptions, level: LoggerLevel, type: string, ...args: Array<any>) {
|
||||
export function log(opts: LogOptions = defaultLogOptions, level: LoggerLevel, type: string | null, ...args: Array<any>) {
|
||||
const event: LogMessage = {
|
||||
type,
|
||||
level,
|
||||
|
@ -79,22 +82,22 @@ export function log(opts: LogOptions = defaultLogOptions, level: LoggerLevel, ty
|
|||
}
|
||||
|
||||
/** Emit a message only shown in debug mode */
|
||||
export function debug(opts: LogOptions, type: string, ...messages: Array<any>) {
|
||||
export function debug(opts: LogOptions, type: string | null, ...messages: Array<any>) {
|
||||
return log(opts, 'debug', type, ...messages);
|
||||
}
|
||||
|
||||
/** Emit a general info message (be careful using this too much!) */
|
||||
export function info(opts: LogOptions, type: string, ...messages: Array<any>) {
|
||||
export function info(opts: LogOptions, type: string | null, ...messages: Array<any>) {
|
||||
return log(opts, 'info', type, ...messages);
|
||||
}
|
||||
|
||||
/** Emit a warning a user should be aware of */
|
||||
export function warn(opts: LogOptions, type: string, ...messages: Array<any>) {
|
||||
export function warn(opts: LogOptions, type: string | null, ...messages: Array<any>) {
|
||||
return log(opts, 'warn', type, ...messages);
|
||||
}
|
||||
|
||||
/** Emit a fatal error message the user should address. */
|
||||
export function error(opts: LogOptions, type: string, ...messages: Array<any>) {
|
||||
export function error(opts: LogOptions, type: string | null, ...messages: Array<any>) {
|
||||
return log(opts, 'error', type, ...messages);
|
||||
}
|
||||
|
||||
|
@ -129,3 +132,12 @@ export const logger = {
|
|||
warn: warn.bind(null, defaultLogOptions),
|
||||
error: error.bind(null, defaultLogOptions),
|
||||
};
|
||||
|
||||
// For silencing libraries that go directly to console.warn
|
||||
export function trapWarn(cb: (...args: any[]) => void = () =>{}) {
|
||||
const warn = console.warn;
|
||||
console.warn = function(...args: any[]) {
|
||||
cb(...args);
|
||||
};
|
||||
return () => console.warn = warn;
|
||||
}
|
Loading…
Reference in a new issue