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
90 changes: 72 additions & 18 deletions goldens/public-api/angular_devkit/build_angular/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,54 @@ import type { ConfigOptions } from 'karma';
import { Configuration } from 'webpack';
import { DevServerBuildOutput } from '@angular-devkit/build-webpack';
import { Observable } from 'rxjs';
import { OutputFile } from 'esbuild';
import type { Plugin as Plugin_2 } from 'esbuild';
import webpack from 'webpack';
import { WebpackLoggingCallback } from '@angular-devkit/build-webpack';

// @public
export interface ApplicationBuilderOptions {
allowedCommonJsDependencies?: string[];
aot?: boolean;
appShell?: boolean;
assets?: AssetPattern_2[];
baseHref?: string;
browser: string;
budgets?: Budget_2[];
crossOrigin?: CrossOrigin_2;
deleteOutputPath?: boolean;
externalDependencies?: string[];
extractLicenses?: boolean;
fileReplacements?: FileReplacement_2[];
i18nDuplicateTranslation?: I18NTranslation_2;
i18nMissingTranslation?: I18NTranslation_2;
index: IndexUnion_2;
inlineStyleLanguage?: InlineStyleLanguage_2;
localize?: Localize_2;
namedChunks?: boolean;
optimization?: OptimizationUnion_2;
outputHashing?: OutputHashing_2;
outputPath: string;
poll?: number;
polyfills?: string[];
prerender?: PrerenderUnion;
preserveSymlinks?: boolean;
progress?: boolean;
scripts?: ScriptElement_2[];
server?: string;
serviceWorker?: ServiceWorker_2;
sourceMap?: SourceMapUnion_2;
ssr?: ServiceWorker_2;
statsJson?: boolean;
stylePreprocessorOptions?: StylePreprocessorOptions_2;
styles?: StyleElement_2[];
subresourceIntegrity?: boolean;
tsConfig: string;
verbose?: boolean;
watch?: boolean;
webWorkerTsConfig?: string;
}

// @public (undocumented)
export type AssetPattern = AssetPatternObject | string;

Expand Down Expand Up @@ -94,6 +139,15 @@ export interface Budget {
warning?: string;
}

// @public
export function buildApplication(options: ApplicationBuilderOptions, context: BuilderContext, plugins?: Plugin_2[]): AsyncIterable<BuilderOutput & {
outputFiles?: BuildOutputFile[];
assetFiles?: {
source: string;
destination: string;
}[];
}>;

// @public
export enum CrossOrigin {
// (undocumented)
Expand Down Expand Up @@ -149,7 +203,7 @@ export function executeDevServerBuilder(options: DevServerBuilderOptions, contex
webpackConfiguration?: ExecutionTransformer<Configuration>;
logging?: WebpackLoggingCallback;
indexHtml?: IndexHtmlTransform;
}): Observable<DevServerBuilderOutput>;
}, plugins?: Plugin_2[]): Observable<DevServerBuilderOutput>;

// @public
export function executeExtractI18nBuilder(options: ExtractI18nBuilderOptions, context: BuilderContext, transforms?: {
Expand Down Expand Up @@ -201,25 +255,25 @@ export interface FileReplacement {

// @public
export interface KarmaBuilderOptions {
assets?: AssetPattern_2[];
assets?: AssetPattern_3[];
browsers?: string;
codeCoverage?: boolean;
codeCoverageExclude?: string[];
exclude?: string[];
fileReplacements?: FileReplacement_2[];
fileReplacements?: FileReplacement_3[];
include?: string[];
inlineStyleLanguage?: InlineStyleLanguage_2;
inlineStyleLanguage?: InlineStyleLanguage_3;
karmaConfig?: string;
main?: string;
poll?: number;
polyfills?: Polyfills_2;
preserveSymlinks?: boolean;
progress?: boolean;
reporters?: string[];
scripts?: ScriptElement_2[];
sourceMap?: SourceMapUnion_2;
stylePreprocessorOptions?: StylePreprocessorOptions_2;
styles?: StyleElement_2[];
scripts?: ScriptElement_3[];
sourceMap?: SourceMapUnion_3;
stylePreprocessorOptions?: StylePreprocessorOptions_3;
styles?: StyleElement_3[];
tsConfig: string;
watch?: boolean;
webWorkerTsConfig?: string;
Expand Down Expand Up @@ -276,30 +330,30 @@ export interface ProtractorBuilderOptions {

// @public (undocumented)
export interface ServerBuilderOptions {
assets?: AssetPattern_3[];
assets?: AssetPattern_4[];
buildOptimizer?: boolean;
deleteOutputPath?: boolean;
// @deprecated
deployUrl?: string;
externalDependencies?: string[];
extractLicenses?: boolean;
fileReplacements?: FileReplacement_3[];
i18nDuplicateTranslation?: I18NTranslation_2;
i18nMissingTranslation?: I18NTranslation_2;
inlineStyleLanguage?: InlineStyleLanguage_3;
localize?: Localize_2;
fileReplacements?: FileReplacement_4[];
i18nDuplicateTranslation?: I18NTranslation_3;
i18nMissingTranslation?: I18NTranslation_3;
inlineStyleLanguage?: InlineStyleLanguage_4;
localize?: Localize_3;
main: string;
namedChunks?: boolean;
optimization?: OptimizationUnion_2;
outputHashing?: OutputHashing_2;
optimization?: OptimizationUnion_3;
outputHashing?: OutputHashing_3;
outputPath: string;
poll?: number;
preserveSymlinks?: boolean;
progress?: boolean;
resourcesOutputPath?: string;
sourceMap?: SourceMapUnion_3;
sourceMap?: SourceMapUnion_4;
statsJson?: boolean;
stylePreprocessorOptions?: StylePreprocessorOptions_3;
stylePreprocessorOptions?: StylePreprocessorOptions_4;
tsConfig: string;
vendorChunk?: boolean;
verbose?: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

import { BuilderContext, BuilderOutput, createBuilder } from '@angular-devkit/architect';
import type { Plugin } from 'esbuild';
import { BuildOutputFile, BuildOutputFileType } from '../../tools/esbuild/bundler-context';
import { purgeStaleBuildCache } from '../../utils/purge-cache';
import { assertCompatibleAngularVersion } from '../../utils/version';
Expand All @@ -15,13 +16,16 @@ import { executeBuild } from './execute-build';
import { ApplicationBuilderInternalOptions, normalizeOptions } from './options';
import { Schema as ApplicationBuilderOptions } from './schema';

export { ApplicationBuilderOptions };

export async function* buildApplicationInternal(
options: ApplicationBuilderInternalOptions,
// TODO: Integrate abort signal support into builder system
context: BuilderContext & { signal?: AbortSignal },
infrastructureSettings?: {
write?: boolean;
},
plugins?: Plugin[],
): AsyncIterable<
BuilderOutput & {
outputFiles?: BuildOutputFile[];
Expand All @@ -42,7 +46,7 @@ export async function* buildApplicationInternal(
return;
}

const normalizedOptions = await normalizeOptions(context, projectName, options);
const normalizedOptions = await normalizeOptions(context, projectName, options, plugins);

yield* runEsBuildBuildAction(
(rebuildState) => executeBuild(normalizedOptions, context, rebuildState),
Expand All @@ -69,16 +73,31 @@ export async function* buildApplicationInternal(
);
}

/**
* Builds an application using the `application` builder with the provided
* options.
*
* Usage of the `plugins` parameter is NOT supported and may cause unexpected
* build output or build failures.
*
* @experimental Direct usage of this function is considered experimental.
*
* @param options The options defined by the builder's schema to use.
* @param context An Architect builder context instance.
* @param plugins An array of plugins to apply to the main code bundling.
* @returns The build output results of the build.
*/
export function buildApplication(
options: ApplicationBuilderOptions,
context: BuilderContext,
plugins?: Plugin[],
): AsyncIterable<
BuilderOutput & {
outputFiles?: BuildOutputFile[];
assetFiles?: { source: string; destination: string }[];
}
> {
return buildApplicationInternal(options, context);
return buildApplicationInternal(options, context, undefined, plugins);
}

export default createBuilder(buildApplication);
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

import { BuilderContext } from '@angular-devkit/architect';
import type { Plugin } from 'esbuild';
import { createRequire } from 'node:module';
import path from 'node:path';
import {
Expand Down Expand Up @@ -71,13 +72,15 @@ export type ApplicationBuilderInternalOptions = Omit<
* @param context The context for current builder execution.
* @param projectName The name of the project for the current execution.
* @param options An object containing the options to use for the build.
* @param plugins An optional array of programmatically supplied build plugins.
* @returns An object containing normalized options required to perform the build.
*/
// eslint-disable-next-line max-lines-per-function
export async function normalizeOptions(
context: BuilderContext,
projectName: string,
options: ApplicationBuilderInternalOptions,
plugins?: Plugin[],
) {
const workspaceRoot = context.workspaceRoot;
const projectMetadata = await context.getProjectMetadata(projectName);
Expand Down Expand Up @@ -295,6 +298,7 @@ export async function normalizeOptions(
namedChunks,
budgets: budgets?.length ? budgets : undefined,
publicPath: deployUrl ? deployUrl : undefined,
plugins: plugins?.length ? plugins : undefined,
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

import { BuilderContext, BuilderOutput, createBuilder } from '@angular-devkit/architect';
import type { Plugin } from 'esbuild';
import { constants as fsConstants } from 'node:fs';
import fs from 'node:fs/promises';
import path from 'node:path';
Expand All @@ -29,6 +30,7 @@ export async function* buildEsbuildBrowser(
infrastructureSettings?: {
write?: boolean;
},
plugins?: Plugin[],
): AsyncIterable<
BuilderOutput & {
outputFiles?: BuildOutputFile[];
Expand All @@ -40,9 +42,14 @@ export async function* buildEsbuildBrowser(
const normalizedOptions = normalizeOptions(userOptions);
const fullOutputPath = path.join(context.workspaceRoot, normalizedOptions.outputPath);

for await (const result of buildApplicationInternal(normalizedOptions, context, {
write: false,
})) {
for await (const result of buildApplicationInternal(
normalizedOptions,
context,
{
write: false,
},
plugins,
)) {
if (infrastructureSettings?.write !== false && result.outputFiles) {
// Write output files
await writeResultFiles(result.outputFiles, result.assetFiles, fullOutputPath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

import type { BuilderContext } from '@angular-devkit/architect';
import type { Plugin } from 'esbuild';
import { EMPTY, Observable, defer, switchMap } from 'rxjs';
import type { ExecutionTransformer } from '../../transforms';
import { checkPort } from '../../utils/check-port';
Expand All @@ -33,6 +34,7 @@ export function execute(
logging?: import('@angular-devkit/build-webpack').WebpackLoggingCallback;
indexHtml?: IndexHtmlTransform;
} = {},
plugins?: Plugin[],
): Observable<DevServerBuilderOutput> {
// Determine project name from builder context target
const projectName = context.target?.project;
Expand All @@ -50,11 +52,23 @@ export function execute(
builderName === '@angular-devkit/build-angular:browser-esbuild' ||
normalizedOptions.forceEsbuild
) {
if (Object.keys(transforms).length > 0) {
throw new Error(
'The `application` and `browser-esbuild` builders do not support Webpack transforms.',
);
}

return defer(() => import('./vite-server')).pipe(
switchMap(({ serveWithVite }) => serveWithVite(normalizedOptions, builderName, context)),
switchMap(({ serveWithVite }) =>
serveWithVite(normalizedOptions, builderName, context, plugins),
),
);
}

if (plugins?.length) {
throw new Error('Only the `application` and `browser-esbuild` builders support plugins.');
}

// Use Webpack for all other browser targets
return defer(() => import('./webpack-server')).pipe(
switchMap(({ serveWebpackBrowser }) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import type { BuilderContext } from '@angular-devkit/architect';
import type { json, logging } from '@angular-devkit/core';
import type { Plugin } from 'esbuild';
import { lookup as lookupMimeType } from 'mrmime';
import assert from 'node:assert';
import { BinaryLike, createHash } from 'node:crypto';
Expand Down Expand Up @@ -48,6 +49,7 @@ export async function* serveWithVite(
serverOptions: NormalizedDevServerOptions,
builderName: string,
context: BuilderContext,
plugins?: Plugin[],
): AsyncIterableIterator<DevServerBuilderOutput> {
// Get the browser configuration from the target name.
const rawBrowserOptions = (await context.getTargetOptions(
Expand Down Expand Up @@ -115,9 +117,14 @@ export async function* serveWithVite(
const generatedFiles = new Map<string, OutputFileRecord>();
const assetFiles = new Map<string, string>();
// TODO: Switch this to an architect schedule call when infrastructure settings are supported
for await (const result of buildEsbuildBrowser(browserOptions, context, {
write: false,
})) {
for await (const result of buildEsbuildBrowser(
browserOptions,
context,
{
write: false,
},
plugins,
)) {
assert(result.outputFiles, 'Builder did not provide result files.');

// Analyze result files for changes
Expand Down
2 changes: 2 additions & 0 deletions packages/angular_devkit/build_angular/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ export {
BrowserBuilderOutput,
} from './builders/browser';

export { buildApplication, ApplicationBuilderOptions } from './builders/application';

export {
executeDevServerBuilder,
DevServerBuilderOptions,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,10 @@ export function createBrowserCodeBundleOptions(
);
}

if (options.plugins) {
buildOptions.plugins?.push(...options.plugins);
}

return buildOptions;
}

Expand Down Expand Up @@ -343,6 +347,10 @@ export function createServerCodeBundleOptions(
);
}

if (options.plugins) {
buildOptions.plugins.push(...options.plugins);
}

return buildOptions;
}

Expand Down