Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 48 additions & 4 deletions packages/angular/build/src/builders/library/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { getSupportedBrowsers } from '../../utils/supported-browsers';
import { assertCompatibleAngularVersion } from '../../utils/version';
import type { BuildWatcher } from '../../utils/watcher';
import { normalizeLibraryOptions } from './options';
import type { BuildActionResult } from './pipeline/build-action';
import { updateWatchedEntryPoints } from './pipeline/entry-points';
import type { createComponentStylesheetBundlerForLibrary } from './pipeline/stylesheet-bundler';
import { loadPackageJson } from './pipeline/utils';
Expand Down Expand Up @@ -185,6 +186,17 @@ export async function* executeLibraryBuilder(
}
}

/**
* Executes a single build iteration with progress reporting, logs any resulting
* messages, and registers newly discovered files with the watcher.
*
* @param message Progress spinner message to display while building.
* @param actionContext The build action context and state.
* @param withProgress Progress wrapper function (`withSpinner` or `withNoProgress`).
* @param watcher Optional file watcher for watch mode.
* @param buildAction The library build action function to execute.
* @returns A promise resolving to the Architect `BuilderOutput`.
*/
async function executeBuild(
message: string,
actionContext: import('./pipeline/build-action').BuildActionContext,
Expand All @@ -196,13 +208,16 @@ async function executeBuild(
const { context, watchedCompilationFiles, isWatchMode, options } = actionContext;

try {
await withProgress(message, () => buildAction(actionContext));
logBuildResult(context.logger, startTime, true, options.outputPath);
if (isWatchMode) {
const result = await withProgress(message, () => buildAction(actionContext));
logMessages(context.logger, result);

const success = result.errors.length === 0;
logBuildResult(context.logger, startTime, success, options.outputPath);
if (success && isWatchMode) {
logCumulativeDurations();
}

return { success: true };
return { success };
} catch (error) {
assertIsError(error);
logBuildResult(context.logger, startTime, false);
Expand Down Expand Up @@ -300,6 +315,7 @@ async function* runWatchLoop(
assertIsError(error);
await buildState.singleProgramCache?.compilationInstance.update?.(changedFiles);
buildState.hasEmittedManifests = false;

yield {
success: false,
error: `Failed to reload 'package.json': ${error.message}`,
Expand Down Expand Up @@ -343,8 +359,36 @@ async function* runWatchLoop(
}
}

/**
* Logs informational, warning, and error messages produced during a build iteration.
*
* @param logger The Architect logger API.
* @param result The build action result containing logs, warnings, and errors.
*/
function logMessages(
logger: logging.LoggerApi,
{ logs, warnings, errors }: BuildActionResult,
): void {
if (logs.length) {
logger.info(logs.join('\n'));
}

if (warnings.length) {
logger.warn(warnings.join('\n'));
}

if (errors.length) {
logger.error(errors.join('\n'));
}
}

/**
* Logs the build completion time and status.
*
* @param logger The Architect logger API.
* @param startTime High-resolution timestamp recorded when the build iteration started.
* @param success Whether the build iteration succeeded without errors.
* @param outputPath Optional output directory path to log on successful builds.
*/
function logBuildResult(
logger: logging.LoggerApi,
Expand Down
Loading
Loading