Skip to content

Commit 4ffe07a

Browse files
committed
feat(@angular-devkit/build-angular): move Vite-based dev-server for application builder to new build system package
With the `application` builder already within the new `@angular/build` package, the Vite-based `dev-server` builder is now also contained within this package. Only the Vite-based aspects of the `dev-server` have been moved and only the support for the `application` builder. The compatibility builder `browser-esbuild` is not supported with `@angular/build:dev-server`. The existing `dev-server` builder found within `@angular-devkit/build-angular` should continue to be used for both the Webpack-based `browser` builder and the esbuild-based compatibility `browser-esbuild` builder. To maintain backwards compatibility, the existing `@angular-devkit/build-angular:dev-server` builder continues to support builders it has previously. No change to existing applications is required.
1 parent c4cd1ed commit 4ffe07a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+2762
-79
lines changed

goldens/public-api/angular/build/index.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import { BuilderContext } from '@angular-devkit/architect';
1010
import { BuilderOutput } from '@angular-devkit/architect';
11+
import type http from 'node:http';
1112
import { OutputFile } from 'esbuild';
1213
import type { Plugin as Plugin_2 } from 'esbuild';
1314

@@ -107,6 +108,51 @@ export enum BuildOutputFileType {
107108
Server = 3
108109
}
109110

111+
// @public
112+
export interface DevServerBuilderOptions {
113+
allowedHosts?: string[];
114+
// @deprecated
115+
browserTarget?: string;
116+
buildTarget?: string;
117+
disableHostCheck?: boolean;
118+
forceEsbuild?: boolean;
119+
headers?: {
120+
[key: string]: string;
121+
};
122+
hmr?: boolean;
123+
host?: string;
124+
liveReload?: boolean;
125+
open?: boolean;
126+
poll?: number;
127+
port?: number;
128+
prebundle?: PrebundleUnion;
129+
proxyConfig?: string;
130+
publicHost?: string;
131+
servePath?: string;
132+
ssl?: boolean;
133+
sslCert?: string;
134+
sslKey?: string;
135+
verbose?: boolean;
136+
watch?: boolean;
137+
}
138+
139+
// @public
140+
export interface DevServerBuilderOutput extends BuilderOutput {
141+
// (undocumented)
142+
address?: string;
143+
// (undocumented)
144+
baseUrl: string;
145+
// (undocumented)
146+
port?: number;
147+
}
148+
149+
// @public
150+
export function executeDevServerBuilder(options: DevServerBuilderOptions, context: BuilderContext, extensions?: {
151+
buildPlugins?: Plugin_2[];
152+
middleware?: ((req: http.IncomingMessage, res: http.ServerResponse, next: (err?: unknown) => void) => void)[];
153+
indexHtmlTransformer?: IndexHtmlTransform;
154+
}): AsyncIterable<DevServerBuilderOutput>;
155+
110156
// (No @packageDocumentation comment for this package)
111157

112158
```

goldens/public-api/angular_devkit/build_angular/index.md

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { BuilderContext } from '@angular-devkit/architect';
1212
import { BuilderOutput } from '@angular-devkit/architect';
1313
import type { ConfigOptions } from 'karma';
1414
import { Configuration } from 'webpack';
15+
import { DevServerBuilderOutput } from '@angular/build';
1516
import type http from 'node:http';
1617
import { IndexHtmlTransform } from '@angular/build/private';
1718
import { json } from '@angular-devkit/core';
@@ -142,15 +143,7 @@ export interface DevServerBuilderOptions {
142143
watch?: boolean;
143144
}
144145

145-
// @public
146-
export interface DevServerBuilderOutput extends BuilderOutput {
147-
// (undocumented)
148-
address?: string;
149-
// (undocumented)
150-
baseUrl: string;
151-
// (undocumented)
152-
port?: number;
153-
}
146+
export { DevServerBuilderOutput }
154147

155148
// @public
156149
export function executeBrowserBuilder(options: BrowserBuilderOptions, context: BuilderContext, transforms?: {

packages/angular/build/BUILD.bazel

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ ts_json_schema(
1212
src = "src/builders/application/schema.json",
1313
)
1414

15+
ts_json_schema(
16+
name = "dev-server_schema",
17+
src = "src/builders/dev-server/schema.json",
18+
)
19+
1520
ts_library(
1621
name = "build",
1722
package_name = "@angular/build",
@@ -28,6 +33,7 @@ ts_library(
2833
],
2934
) + [
3035
"//packages/angular/build:src/builders/application/schema.ts",
36+
"//packages/angular/build:src/builders/dev-server/schema.ts",
3137
],
3238
data = glob(
3339
include = [
@@ -57,18 +63,21 @@ ts_library(
5763
"@npm//@babel/helper-split-export-declaration",
5864
"@npm//@types/babel__core",
5965
"@npm//@types/browserslist",
66+
"@npm//@types/inquirer",
6067
"@npm//@types/less",
6168
"@npm//@types/node",
6269
"@npm//@types/picomatch",
6370
"@npm//@types/semver",
6471
"@npm//@types/watchpack",
72+
"@npm//@vitejs/plugin-basic-ssl",
6573
"@npm//ansi-colors",
6674
"@npm//autoprefixer",
6775
"@npm//browserslist",
6876
"@npm//critters",
6977
"@npm//esbuild",
7078
"@npm//fast-glob",
7179
"@npm//https-proxy-agent",
80+
"@npm//inquirer",
7281
"@npm//less",
7382
"@npm//magic-string",
7483
"@npm//mrmime",
@@ -81,6 +90,7 @@ ts_library(
8190
"@npm//tslib",
8291
"@npm//typescript",
8392
"@npm//undici",
93+
"@npm//vite",
8494
"@npm//watchpack",
8595
],
8696
)
@@ -132,6 +142,11 @@ ts_library(
132142
"//packages/angular_devkit/core",
133143
"//packages/angular_devkit/core/node",
134144

145+
# dev server only test deps
146+
"@npm//@types/http-proxy",
147+
"@npm//http-proxy",
148+
"@npm//puppeteer",
149+
135150
# Base dependencies for the application in hello-world-app.
136151
"@npm//@angular/common",
137152
"@npm//@angular/compiler",

packages/angular/build/builders.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
{
22
"builders": {
33
"application": {
4-
"implementation": "./src/builders/application",
4+
"implementation": "./src/builders/application/index",
55
"schema": "./src/builders/application/schema.json",
66
"description": "Build an application."
7+
},
8+
"dev-server": {
9+
"implementation": "./src/builders/dev-server/index",
10+
"schema": "./src/builders/dev-server/schema.json",
11+
"description": "Execute a development server for an application."
712
}
813
}
914
}

packages/angular/build/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,13 @@
2323
"@babel/core": "7.24.4",
2424
"@babel/helper-annotate-as-pure": "7.22.5",
2525
"@babel/helper-split-export-declaration": "7.22.6",
26+
"@vitejs/plugin-basic-ssl": "1.1.0",
2627
"browserslist": "^4.23.0",
2728
"critters": "0.0.22",
2829
"esbuild": "0.20.2",
2930
"fast-glob": "3.3.2",
3031
"https-proxy-agent": "7.0.4",
32+
"inquirer": "9.2.19",
3133
"less": "4.2.0",
3234
"magic-string": "0.30.10",
3335
"mrmime": "2.0.0",
@@ -38,6 +40,7 @@
3840
"sass": "1.75.0",
3941
"semver": "7.6.0",
4042
"undici": "6.13.0",
43+
"vite": "5.2.10",
4144
"watchpack": "2.4.1"
4245
},
4346
"peerDependencies": {
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import type { BuilderContext } from '@angular-devkit/architect';
10+
import type { Plugin } from 'esbuild';
11+
import type http from 'node:http';
12+
import { checkPort } from '../../utils/check-port';
13+
import {
14+
type IndexHtmlTransform,
15+
buildApplicationInternal,
16+
purgeStaleBuildCache,
17+
} from './internal';
18+
import { normalizeOptions } from './options';
19+
import type { DevServerBuilderOutput } from './output';
20+
import type { Schema as DevServerBuilderOptions } from './schema';
21+
import { serveWithVite } from './vite-server';
22+
23+
/**
24+
* A Builder that executes a development server based on the provided browser target option.
25+
*
26+
* Usage of the `transforms` and/or `extensions` parameters is NOT supported and may cause
27+
* unexpected build output or build failures.
28+
*
29+
* @param options Dev Server options.
30+
* @param context The build context.
31+
* @param extensions An optional object containing an array of build plugins (esbuild-based)
32+
* and/or HTTP request middleware.
33+
*
34+
* @experimental Direct usage of this function is considered experimental.
35+
*/
36+
export async function* execute(
37+
options: DevServerBuilderOptions,
38+
context: BuilderContext,
39+
extensions?: {
40+
buildPlugins?: Plugin[];
41+
middleware?: ((
42+
req: http.IncomingMessage,
43+
res: http.ServerResponse,
44+
next: (err?: unknown) => void,
45+
) => void)[];
46+
indexHtmlTransformer?: IndexHtmlTransform;
47+
},
48+
): AsyncIterable<DevServerBuilderOutput> {
49+
// Determine project name from builder context target
50+
const projectName = context.target?.project;
51+
if (!projectName) {
52+
context.logger.error(`The "dev-server" builder requires a target to be specified.`);
53+
54+
return;
55+
}
56+
57+
const { builderName, normalizedOptions } = await initialize(options, projectName, context);
58+
59+
// Warn if the initial options provided by the user enable prebundling but caching is disabled
60+
if (options.prebundle && !normalizedOptions.cacheOptions.enabled) {
61+
context.logger.warn(
62+
`Prebundling has been configured but will not be used because caching has been disabled.`,
63+
);
64+
}
65+
66+
yield* serveWithVite(
67+
normalizedOptions,
68+
builderName,
69+
(options, context, plugins) =>
70+
buildApplicationInternal(options, context, { write: false }, { codePlugins: plugins }),
71+
context,
72+
{ indexHtml: extensions?.indexHtmlTransformer },
73+
extensions,
74+
);
75+
}
76+
77+
async function initialize(
78+
initialOptions: DevServerBuilderOptions,
79+
projectName: string,
80+
context: BuilderContext,
81+
) {
82+
// Purge old build disk cache.
83+
await purgeStaleBuildCache(context);
84+
85+
const normalizedOptions = await normalizeOptions(context, projectName, initialOptions);
86+
const builderName = await context.getBuilderNameForTarget(normalizedOptions.buildTarget);
87+
88+
if (
89+
!normalizedOptions.disableHostCheck &&
90+
!/^127\.\d+\.\d+\.\d+/g.test(normalizedOptions.host) &&
91+
normalizedOptions.host !== 'localhost'
92+
) {
93+
context.logger.warn(`
94+
Warning: This is a simple server for use in testing or debugging Angular applications
95+
locally. It hasn't been reviewed for security issues.
96+
97+
Binding this server to an open connection can result in compromising your application or
98+
computer. Using a different host than the one passed to the "--host" flag might result in
99+
websocket connection issues. You might need to use "--disable-host-check" if that's the
100+
case.
101+
`);
102+
}
103+
104+
if (normalizedOptions.disableHostCheck) {
105+
context.logger.warn(
106+
'Warning: Running a server with --disable-host-check is a security risk. ' +
107+
'See https://medium.com/webpack/webpack-dev-server-middleware-security-issues-1489d950874a for more information.',
108+
);
109+
}
110+
111+
normalizedOptions.port = await checkPort(normalizedOptions.port, normalizedOptions.host);
112+
113+
return {
114+
builderName,
115+
normalizedOptions,
116+
};
117+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import { createBuilder } from '@angular-devkit/architect';
10+
import { execute } from './builder';
11+
import { DevServerBuilderOutput } from './output';
12+
import { Schema as DevServerBuilderOptions } from './schema';
13+
14+
export { DevServerBuilderOptions, DevServerBuilderOutput, execute as executeDevServerBuilder };
15+
export default createBuilder<DevServerBuilderOptions, DevServerBuilderOutput>(execute);
16+
17+
// Temporary export to support specs
18+
export { execute as executeDevServer };
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
export { BuildOutputFile, BuildOutputFileType } from '@angular/build';
10+
export { createRxjsEsmResolutionPlugin } from '../../tools/esbuild/rxjs-esm-resolution-plugin';
11+
export { JavaScriptTransformer } from '../../tools/esbuild/javascript-transformer';
12+
export { getFeatureSupport, isZonelessApp } from '../../tools/esbuild/utils';
13+
export { renderPage } from '../../utils/server-rendering/render-page';
14+
export { type IndexHtmlTransform } from '../../utils/index-file/index-html-generator';
15+
export { purgeStaleBuildCache } from '../../utils/purge-cache';
16+
export { getSupportedBrowsers } from '../../utils/supported-browsers';
17+
export { transformSupportedBrowsersToTargets } from '../../tools/esbuild/utils';
18+
export { buildApplicationInternal } from '../../builders/application';
19+
export { ApplicationBuilderInternalOptions } from '../../builders/application/options';
20+
export { ExternalResultMetadata } from '../../tools/esbuild/bundler-execution-result';

0 commit comments

Comments
 (0)