@angular-devkit/build-angular 17.2.0-next.1 → 17.2.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +13 -13
- package/src/builders/application/build-action.d.ts +1 -0
- package/src/builders/application/build-action.js +18 -14
- package/src/builders/application/index.js +1 -0
- package/src/builders/application/options.d.ts +10 -2
- package/src/builders/application/options.js +3 -1
- package/src/builders/application/schema.d.ts +13 -0
- package/src/builders/application/schema.json +12 -0
- package/src/builders/browser/index.js +3 -2
- package/src/builders/dev-server/builder.js +13 -2
- package/src/builders/dev-server/options.d.ts +1 -0
- package/src/builders/dev-server/options.js +3 -1
- package/src/builders/dev-server/schema.d.ts +19 -0
- package/src/builders/dev-server/schema.json +18 -0
- package/src/builders/dev-server/vite-server.js +6 -6
- package/src/builders/server/index.js +3 -2
- package/src/tools/esbuild/angular/compiler-plugin.js +1 -1
- package/src/tools/esbuild/application-code-bundle.js +5 -2
- package/src/tools/esbuild/bundler-context.d.ts +1 -0
- package/src/tools/esbuild/bundler-context.js +11 -5
- package/src/tools/esbuild/external-packages-plugin.d.ts +3 -1
- package/src/tools/esbuild/external-packages-plugin.js +9 -5
- package/src/tools/esbuild/index-html-generator.js +4 -2
- package/src/tools/vite/angular-memory-plugin.js +13 -0
- package/src/tools/webpack/utils/stats.js +3 -2
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angular-devkit/build-angular",
|
|
3
|
-
"version": "17.2.0-
|
|
3
|
+
"version": "17.2.0-rc.0",
|
|
4
4
|
"description": "Angular Webpack Build Facade",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"typings": "src/index.d.ts",
|
|
7
7
|
"builders": "builders.json",
|
|
8
8
|
"dependencies": {
|
|
9
9
|
"@ampproject/remapping": "2.2.1",
|
|
10
|
-
"@angular-devkit/architect": "0.1702.0-
|
|
11
|
-
"@angular-devkit/build-webpack": "0.1702.0-
|
|
12
|
-
"@angular-devkit/core": "17.2.0-
|
|
10
|
+
"@angular-devkit/architect": "0.1702.0-rc.0",
|
|
11
|
+
"@angular-devkit/build-webpack": "0.1702.0-rc.0",
|
|
12
|
+
"@angular-devkit/core": "17.2.0-rc.0",
|
|
13
13
|
"@babel/core": "7.23.9",
|
|
14
14
|
"@babel/generator": "7.23.6",
|
|
15
15
|
"@babel/helper-annotate-as-pure": "7.22.5",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"@babel/preset-env": "7.23.9",
|
|
21
21
|
"@babel/runtime": "7.23.9",
|
|
22
22
|
"@discoveryjs/json-ext": "0.5.7",
|
|
23
|
-
"@ngtools/webpack": "17.2.0-
|
|
23
|
+
"@ngtools/webpack": "17.2.0-rc.0",
|
|
24
24
|
"@vitejs/plugin-basic-ssl": "1.1.0",
|
|
25
25
|
"ansi-colors": "4.1.3",
|
|
26
26
|
"autoprefixer": "10.4.17",
|
|
@@ -34,37 +34,37 @@
|
|
|
34
34
|
"fast-glob": "3.3.2",
|
|
35
35
|
"https-proxy-agent": "7.0.2",
|
|
36
36
|
"http-proxy-middleware": "2.0.6",
|
|
37
|
-
"inquirer": "9.2.
|
|
37
|
+
"inquirer": "9.2.14",
|
|
38
38
|
"jsonc-parser": "3.2.1",
|
|
39
39
|
"karma-source-map-support": "1.4.0",
|
|
40
40
|
"less": "4.2.0",
|
|
41
41
|
"less-loader": "11.1.0",
|
|
42
42
|
"license-webpack-plugin": "4.0.2",
|
|
43
43
|
"loader-utils": "3.2.1",
|
|
44
|
-
"magic-string": "0.30.
|
|
45
|
-
"mini-css-extract-plugin": "2.
|
|
44
|
+
"magic-string": "0.30.7",
|
|
45
|
+
"mini-css-extract-plugin": "2.8.0",
|
|
46
46
|
"mrmime": "2.0.0",
|
|
47
47
|
"open": "8.4.2",
|
|
48
48
|
"ora": "5.4.1",
|
|
49
49
|
"parse5-html-rewriting-stream": "7.0.0",
|
|
50
|
-
"picomatch": "
|
|
50
|
+
"picomatch": "4.0.1",
|
|
51
51
|
"piscina": "4.3.1",
|
|
52
|
-
"postcss": "8.4.
|
|
52
|
+
"postcss": "8.4.35",
|
|
53
53
|
"postcss-loader": "8.1.0",
|
|
54
54
|
"resolve-url-loader": "5.0.0",
|
|
55
55
|
"rxjs": "7.8.1",
|
|
56
56
|
"sass": "1.70.0",
|
|
57
57
|
"sass-loader": "14.1.0",
|
|
58
|
-
"semver": "7.
|
|
58
|
+
"semver": "7.6.0",
|
|
59
59
|
"source-map-loader": "5.0.0",
|
|
60
60
|
"source-map-support": "0.5.21",
|
|
61
61
|
"terser": "5.27.0",
|
|
62
62
|
"tree-kill": "1.2.2",
|
|
63
63
|
"tslib": "2.6.2",
|
|
64
|
-
"undici": "6.
|
|
64
|
+
"undici": "6.6.2",
|
|
65
65
|
"vite": "5.0.12",
|
|
66
66
|
"watchpack": "2.4.0",
|
|
67
|
-
"webpack": "5.90.
|
|
67
|
+
"webpack": "5.90.1",
|
|
68
68
|
"webpack-dev-middleware": "6.1.1",
|
|
69
69
|
"webpack-dev-server": "4.15.1",
|
|
70
70
|
"webpack-merge": "5.10.0",
|
|
@@ -26,4 +26,5 @@ export declare function runEsBuildBuildAction(action: (rebuildState?: RebuildSta
|
|
|
26
26
|
poll?: number;
|
|
27
27
|
signal?: AbortSignal;
|
|
28
28
|
preserveSymlinks?: boolean;
|
|
29
|
+
clearScreen?: boolean;
|
|
29
30
|
}): AsyncIterable<(ExecutionResult['outputWithFiles'] | ExecutionResult['output']) & BuilderOutput>;
|
|
@@ -40,8 +40,21 @@ const sass_language_1 = require("../../tools/esbuild/stylesheets/sass-language")
|
|
|
40
40
|
const utils_1 = require("../../tools/esbuild/utils");
|
|
41
41
|
const delete_output_dir_1 = require("../../utils/delete-output-dir");
|
|
42
42
|
const environment_options_1 = require("../../utils/environment-options");
|
|
43
|
+
// Watch workspace for package manager changes
|
|
44
|
+
const packageWatchFiles = [
|
|
45
|
+
// manifest can affect module resolution
|
|
46
|
+
'package.json',
|
|
47
|
+
// npm lock file
|
|
48
|
+
'package-lock.json',
|
|
49
|
+
// pnpm lock file
|
|
50
|
+
'pnpm-lock.yaml',
|
|
51
|
+
// yarn lock file including Yarn PnP manifest files (https://yarnpkg.com/advanced/pnp-spec/)
|
|
52
|
+
'yarn.lock',
|
|
53
|
+
'.pnp.cjs',
|
|
54
|
+
'.pnp.data.json',
|
|
55
|
+
];
|
|
43
56
|
async function* runEsBuildBuildAction(action, options) {
|
|
44
|
-
const { writeToFileSystemFilter, writeToFileSystem, watch, poll, logger, deleteOutputPath, cacheOptions, outputOptions, verbose, projectRoot, workspaceRoot, progress, preserveSymlinks, } = options;
|
|
57
|
+
const { writeToFileSystemFilter, writeToFileSystem, watch, poll, clearScreen, logger, deleteOutputPath, cacheOptions, outputOptions, verbose, projectRoot, workspaceRoot, progress, preserveSymlinks, } = options;
|
|
45
58
|
if (deleteOutputPath && writeToFileSystem) {
|
|
46
59
|
await (0, delete_output_dir_1.deleteOutputDir)(workspaceRoot, outputOptions.base, [
|
|
47
60
|
outputOptions.browser,
|
|
@@ -93,19 +106,6 @@ async function* runEsBuildBuildAction(action, options) {
|
|
|
93
106
|
if (environment_options_1.shouldWatchRoot) {
|
|
94
107
|
watcher.add(projectRoot);
|
|
95
108
|
}
|
|
96
|
-
// Watch workspace for package manager changes
|
|
97
|
-
const packageWatchFiles = [
|
|
98
|
-
// manifest can affect module resolution
|
|
99
|
-
'package.json',
|
|
100
|
-
// npm lock file
|
|
101
|
-
'package-lock.json',
|
|
102
|
-
// pnpm lock file
|
|
103
|
-
'pnpm-lock.yaml',
|
|
104
|
-
// yarn lock file including Yarn PnP manifest files (https://yarnpkg.com/advanced/pnp-spec/)
|
|
105
|
-
'yarn.lock',
|
|
106
|
-
'.pnp.cjs',
|
|
107
|
-
'.pnp.data.json',
|
|
108
|
-
];
|
|
109
109
|
watcher.add(packageWatchFiles
|
|
110
110
|
.map((file) => node_path_1.default.join(workspaceRoot, file))
|
|
111
111
|
.filter((file) => (0, node_fs_1.existsSync)(file)));
|
|
@@ -136,6 +136,10 @@ async function* runEsBuildBuildAction(action, options) {
|
|
|
136
136
|
if (options.signal?.aborted) {
|
|
137
137
|
break;
|
|
138
138
|
}
|
|
139
|
+
if (clearScreen) {
|
|
140
|
+
// eslint-disable-next-line no-console
|
|
141
|
+
console.clear();
|
|
142
|
+
}
|
|
139
143
|
if (verbose) {
|
|
140
144
|
logger.info(changes.toDebugString());
|
|
141
145
|
}
|
|
@@ -90,6 +90,7 @@ context, infrastructureSettings, extensions) {
|
|
|
90
90
|
projectRoot: normalizedOptions.projectRoot,
|
|
91
91
|
workspaceRoot: normalizedOptions.workspaceRoot,
|
|
92
92
|
progress: normalizedOptions.progress,
|
|
93
|
+
clearScreen: normalizedOptions.clearScreen,
|
|
93
94
|
writeToFileSystem,
|
|
94
95
|
// For app-shell and SSG server files are not required by users.
|
|
95
96
|
// Omit these when SSR is not enabled.
|
|
@@ -31,7 +31,9 @@ interface InternalOptions {
|
|
|
31
31
|
* Indicates whether all node packages should be marked as external.
|
|
32
32
|
* Currently used by the dev-server to support prebundling.
|
|
33
33
|
*/
|
|
34
|
-
externalPackages?: boolean
|
|
34
|
+
externalPackages?: boolean | {
|
|
35
|
+
exclude: string[];
|
|
36
|
+
};
|
|
35
37
|
/**
|
|
36
38
|
* Forces the output from the localize post-processing to not create nested directories per locale output.
|
|
37
39
|
* This is only used by the development server which currently only supports a single locale per build.
|
|
@@ -72,7 +74,9 @@ export declare function normalizeOptions(context: BuilderContext, projectName: s
|
|
|
72
74
|
polyfills: string[] | undefined;
|
|
73
75
|
poll: number | undefined;
|
|
74
76
|
progress: boolean;
|
|
75
|
-
externalPackages: boolean |
|
|
77
|
+
externalPackages: boolean | {
|
|
78
|
+
exclude: string[];
|
|
79
|
+
} | undefined;
|
|
76
80
|
preserveSymlinks: boolean;
|
|
77
81
|
stylePreprocessorOptions: import("./schema").StylePreprocessorOptions | undefined;
|
|
78
82
|
subresourceIntegrity: boolean | undefined;
|
|
@@ -139,5 +143,9 @@ export declare function normalizeOptions(context: BuilderContext, projectName: s
|
|
|
139
143
|
loaderExtensions: Record<string, "binary" | "file" | "text"> | undefined;
|
|
140
144
|
jsonLogs: boolean;
|
|
141
145
|
colors: boolean;
|
|
146
|
+
clearScreen: boolean | undefined;
|
|
147
|
+
define: {
|
|
148
|
+
[key: string]: string;
|
|
149
|
+
} | undefined;
|
|
142
150
|
}>;
|
|
143
151
|
export {};
|
|
@@ -178,7 +178,7 @@ async function normalizeOptions(context, projectName, options, extensions) {
|
|
|
178
178
|
};
|
|
179
179
|
}
|
|
180
180
|
// Initial options to keep
|
|
181
|
-
const { allowedCommonJsDependencies, aot, baseHref, crossOrigin, externalDependencies, extractLicenses, inlineStyleLanguage = 'css', outExtension, serviceWorker, poll, polyfills, statsJson, stylePreprocessorOptions, subresourceIntegrity, verbose, watch, progress = true, externalPackages, deleteOutputPath, namedChunks, budgets, deployUrl, } = options;
|
|
181
|
+
const { allowedCommonJsDependencies, aot, baseHref, crossOrigin, externalDependencies, extractLicenses, inlineStyleLanguage = 'css', outExtension, serviceWorker, poll, polyfills, statsJson, stylePreprocessorOptions, subresourceIntegrity, verbose, watch, progress = true, externalPackages, deleteOutputPath, namedChunks, budgets, deployUrl, clearScreen, define, } = options;
|
|
182
182
|
// Return all the normalized options
|
|
183
183
|
return {
|
|
184
184
|
advancedOptimizations: !!aot && optimizationOptions.scripts,
|
|
@@ -230,6 +230,8 @@ async function normalizeOptions(context, projectName, options, extensions) {
|
|
|
230
230
|
loaderExtensions,
|
|
231
231
|
jsonLogs: environment_options_1.useJSONBuildLogs,
|
|
232
232
|
colors: color_1.colors.enabled,
|
|
233
|
+
clearScreen,
|
|
234
|
+
define,
|
|
233
235
|
};
|
|
234
236
|
}
|
|
235
237
|
exports.normalizeOptions = normalizeOptions;
|
|
@@ -33,10 +33,23 @@ export interface Schema {
|
|
|
33
33
|
* set.
|
|
34
34
|
*/
|
|
35
35
|
budgets?: Budget[];
|
|
36
|
+
/**
|
|
37
|
+
* Automatically clear the terminal screen during rebuilds.
|
|
38
|
+
*/
|
|
39
|
+
clearScreen?: boolean;
|
|
36
40
|
/**
|
|
37
41
|
* Define the crossorigin attribute setting of elements that provide CORS support.
|
|
38
42
|
*/
|
|
39
43
|
crossOrigin?: CrossOrigin;
|
|
44
|
+
/**
|
|
45
|
+
* Defines global identifiers that will be replaced with a specified constant value when
|
|
46
|
+
* found in any JavaScript or TypeScript code including libraries. The value will be used
|
|
47
|
+
* directly. String values must be put in quotes. Identifiers within Angular metadata such
|
|
48
|
+
* as Component Decorators will not be replaced.
|
|
49
|
+
*/
|
|
50
|
+
define?: {
|
|
51
|
+
[key: string]: string;
|
|
52
|
+
};
|
|
40
53
|
/**
|
|
41
54
|
* Delete the output path before building.
|
|
42
55
|
*/
|
|
@@ -133,6 +133,11 @@
|
|
|
133
133
|
},
|
|
134
134
|
"default": []
|
|
135
135
|
},
|
|
136
|
+
"clearScreen": {
|
|
137
|
+
"type": "boolean",
|
|
138
|
+
"default": false,
|
|
139
|
+
"description": "Automatically clear the terminal screen during rebuilds."
|
|
140
|
+
},
|
|
136
141
|
"optimization": {
|
|
137
142
|
"description": "Enables optimization of the build output. Including minification of scripts and styles, tree-shaking, dead-code elimination, inlining of critical CSS and fonts inlining. For more information, see https://angular.io/guide/workspace-config#optimization-configuration.",
|
|
138
143
|
"default": true,
|
|
@@ -211,6 +216,13 @@
|
|
|
211
216
|
"^\\.\\S+$": { "enum": ["text", "binary", "file", "empty"] }
|
|
212
217
|
}
|
|
213
218
|
},
|
|
219
|
+
"define": {
|
|
220
|
+
"description": "Defines global identifiers that will be replaced with a specified constant value when found in any JavaScript or TypeScript code including libraries. The value will be used directly. String values must be put in quotes. Identifiers within Angular metadata such as Component Decorators will not be replaced.",
|
|
221
|
+
"type": "object",
|
|
222
|
+
"additionalProperties": {
|
|
223
|
+
"type": "string"
|
|
224
|
+
}
|
|
225
|
+
},
|
|
214
226
|
"fileReplacements": {
|
|
215
227
|
"description": "Replace compilation source files with other compilation source files in the build.",
|
|
216
228
|
"type": "array",
|
|
@@ -120,8 +120,9 @@ function buildWebpackBrowser(options, context, transforms = {}) {
|
|
|
120
120
|
webpackFactory: require('webpack'),
|
|
121
121
|
logging: transforms.logging ||
|
|
122
122
|
((stats, config) => {
|
|
123
|
-
if (options.verbose) {
|
|
124
|
-
|
|
123
|
+
if (options.verbose && config.stats !== false) {
|
|
124
|
+
const statsOptions = config.stats === true ? undefined : config.stats;
|
|
125
|
+
context.logger.info(stats.toString(statsOptions));
|
|
125
126
|
}
|
|
126
127
|
}),
|
|
127
128
|
}).pipe((0, rxjs_1.concatMap)(
|
|
@@ -63,8 +63,16 @@ function execute(options, context, transforms = {}, extensions) {
|
|
|
63
63
|
if (transforms?.logging || transforms?.webpackConfiguration) {
|
|
64
64
|
throw new Error('The `application` and `browser-esbuild` builders do not support Webpack transforms.');
|
|
65
65
|
}
|
|
66
|
+
// Warn if the initial options provided by the user enable prebundling but caching is disabled
|
|
67
|
+
if (options.prebundle && !normalizedOptions.cacheOptions.enabled) {
|
|
68
|
+
context.logger.warn(`Prebundling has been configured but will not be used because caching has been disabled.`);
|
|
69
|
+
}
|
|
66
70
|
return (0, rxjs_1.defer)(() => Promise.resolve().then(() => __importStar(require('./vite-server')))).pipe((0, rxjs_1.switchMap)(({ serveWithVite }) => serveWithVite(normalizedOptions, builderName, context, transforms, extensions)));
|
|
67
71
|
}
|
|
72
|
+
// Warn if the initial options provided by the user enable prebundling with Webpack-based builders
|
|
73
|
+
if (options.prebundle) {
|
|
74
|
+
context.logger.warn(`Prebundling has been configured but will not be used because it is not supported by the "${builderName}" builder.`);
|
|
75
|
+
}
|
|
68
76
|
if (extensions?.buildPlugins?.length) {
|
|
69
77
|
throw new Error('Only the `application` and `browser-esbuild` builders support plugins.');
|
|
70
78
|
}
|
|
@@ -80,7 +88,10 @@ async function initialize(initialOptions, projectName, context, builderSelector
|
|
|
80
88
|
// Purge old build disk cache.
|
|
81
89
|
await (0, purge_cache_1.purgeStaleBuildCache)(context);
|
|
82
90
|
const normalizedOptions = await (0, options_1.normalizeOptions)(context, projectName, initialOptions);
|
|
83
|
-
const builderName =
|
|
91
|
+
const builderName = builderSelector({
|
|
92
|
+
builderName: await context.getBuilderNameForTarget(normalizedOptions.buildTarget),
|
|
93
|
+
forceEsbuild: !!normalizedOptions.forceEsbuild,
|
|
94
|
+
}, context.logger);
|
|
84
95
|
if (!normalizedOptions.disableHostCheck &&
|
|
85
96
|
!/^127\.\d+\.\d+\.\d+/g.test(normalizedOptions.host) &&
|
|
86
97
|
normalizedOptions.host !== 'localhost') {
|
|
@@ -100,7 +111,7 @@ case.
|
|
|
100
111
|
}
|
|
101
112
|
normalizedOptions.port = await (0, check_port_1.checkPort)(normalizedOptions.port, normalizedOptions.host);
|
|
102
113
|
return {
|
|
103
|
-
builderName
|
|
114
|
+
builderName,
|
|
104
115
|
normalizedOptions,
|
|
105
116
|
};
|
|
106
117
|
}
|
|
@@ -33,7 +33,7 @@ async function normalizeOptions(context, projectName, options) {
|
|
|
33
33
|
const buildTargetSpecifier = options.buildTarget ?? options.browserTarget ?? `::development`;
|
|
34
34
|
const buildTarget = (0, architect_1.targetFromTargetString)(buildTargetSpecifier, projectName, 'build');
|
|
35
35
|
// Initial options to keep
|
|
36
|
-
const { host, port, poll, open, verbose, watch, allowedHosts, disableHostCheck, liveReload, hmr, headers, proxyConfig, servePath, publicHost, ssl, sslCert, sslKey, forceEsbuild, } = options;
|
|
36
|
+
const { host, port, poll, open, verbose, watch, allowedHosts, disableHostCheck, liveReload, hmr, headers, proxyConfig, servePath, publicHost, ssl, sslCert, sslKey, forceEsbuild, prebundle, } = options;
|
|
37
37
|
// Return all the normalized options
|
|
38
38
|
return {
|
|
39
39
|
buildTarget,
|
|
@@ -58,6 +58,8 @@ async function normalizeOptions(context, projectName, options) {
|
|
|
58
58
|
sslCert,
|
|
59
59
|
sslKey,
|
|
60
60
|
forceEsbuild,
|
|
61
|
+
// Prebundling defaults to true but requires caching to function
|
|
62
|
+
prebundle: cacheOptions.enabled && (prebundle ?? true),
|
|
61
63
|
};
|
|
62
64
|
}
|
|
63
65
|
exports.normalizeOptions = normalizeOptions;
|
|
@@ -58,6 +58,12 @@ export interface Schema {
|
|
|
58
58
|
* Port to listen on.
|
|
59
59
|
*/
|
|
60
60
|
port?: number;
|
|
61
|
+
/**
|
|
62
|
+
* Enable and control the Vite-based development server's prebundling capabilities. To
|
|
63
|
+
* enable prebundling, the Angular CLI cache must also be enabled. This option has no effect
|
|
64
|
+
* when using the 'browser' or other Webpack-based builders.
|
|
65
|
+
*/
|
|
66
|
+
prebundle?: PrebundleUnion;
|
|
61
67
|
/**
|
|
62
68
|
* Proxy configuration file. For more information, see
|
|
63
69
|
* https://angular.io/guide/build#proxying-to-a-backend-server.
|
|
@@ -94,3 +100,16 @@ export interface Schema {
|
|
|
94
100
|
*/
|
|
95
101
|
watch?: boolean;
|
|
96
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* Enable and control the Vite-based development server's prebundling capabilities. To
|
|
105
|
+
* enable prebundling, the Angular CLI cache must also be enabled. This option has no effect
|
|
106
|
+
* when using the 'browser' or other Webpack-based builders.
|
|
107
|
+
*/
|
|
108
|
+
export type PrebundleUnion = boolean | PrebundleClass;
|
|
109
|
+
export interface PrebundleClass {
|
|
110
|
+
/**
|
|
111
|
+
* List of package imports that should not be prebundled by the development server. The
|
|
112
|
+
* packages will be bundled into the application code itself.
|
|
113
|
+
*/
|
|
114
|
+
exclude: string[];
|
|
115
|
+
}
|
|
@@ -106,6 +106,24 @@
|
|
|
106
106
|
"type": "boolean",
|
|
107
107
|
"description": "Force the development server to use the 'browser-esbuild' builder when building. This is a developer preview option for the esbuild-based build system.",
|
|
108
108
|
"default": false
|
|
109
|
+
},
|
|
110
|
+
"prebundle": {
|
|
111
|
+
"description": "Enable and control the Vite-based development server's prebundling capabilities. To enable prebundling, the Angular CLI cache must also be enabled. This option has no effect when using the 'browser' or other Webpack-based builders.",
|
|
112
|
+
"oneOf": [
|
|
113
|
+
{ "type": "boolean" },
|
|
114
|
+
{
|
|
115
|
+
"type": "object",
|
|
116
|
+
"properties": {
|
|
117
|
+
"exclude": {
|
|
118
|
+
"description": "List of package imports that should not be prebundled by the development server. The packages will be bundled into the application code itself.",
|
|
119
|
+
"type": "array",
|
|
120
|
+
"items": { "type": "string" }
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
"additionalProperties": false,
|
|
124
|
+
"required": ["exclude"]
|
|
125
|
+
}
|
|
126
|
+
]
|
|
109
127
|
}
|
|
110
128
|
},
|
|
111
129
|
"additionalProperties": false,
|
|
@@ -66,16 +66,15 @@ async function* serveWithVite(serverOptions, builderName, context, transformers,
|
|
|
66
66
|
// Avoid bundling and processing the ssr entry-point as this is not used by the dev-server.
|
|
67
67
|
browserOptions.ssr = true;
|
|
68
68
|
// https://nodejs.org/api/process.html#processsetsourcemapsenabledval
|
|
69
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
70
69
|
process.setSourceMapsEnabled(true);
|
|
71
70
|
}
|
|
72
71
|
// Set all packages as external to support Vite's prebundle caching
|
|
73
|
-
browserOptions.externalPackages = serverOptions.
|
|
72
|
+
browserOptions.externalPackages = serverOptions.prebundle;
|
|
74
73
|
const baseHref = browserOptions.baseHref;
|
|
75
74
|
if (serverOptions.servePath === undefined && baseHref !== undefined) {
|
|
76
75
|
// Remove trailing slash
|
|
77
76
|
serverOptions.servePath =
|
|
78
|
-
baseHref[baseHref.length - 1] === '/' ? baseHref.slice(0, -1) : baseHref;
|
|
77
|
+
baseHref !== './' && baseHref[baseHref.length - 1] === '/' ? baseHref.slice(0, -1) : baseHref;
|
|
79
78
|
}
|
|
80
79
|
// The development server currently only supports a single locale when localizing.
|
|
81
80
|
// This matches the behavior of the Webpack-based development server but could be expanded in the future.
|
|
@@ -341,7 +340,8 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
|
|
|
341
340
|
publicDir: false,
|
|
342
341
|
esbuild: false,
|
|
343
342
|
mode: 'development',
|
|
344
|
-
|
|
343
|
+
// We use custom as we do not rely on Vite's htmlFallbackMiddleware and indexHtmlMiddleware.
|
|
344
|
+
appType: 'custom',
|
|
345
345
|
css: {
|
|
346
346
|
devSourcemap: true,
|
|
347
347
|
},
|
|
@@ -392,7 +392,7 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
|
|
|
392
392
|
* - Breaks RxJs (Unless it is added as external). See: https://github.com/angular/angular-cli/issues/26235
|
|
393
393
|
*/
|
|
394
394
|
// Only enable with caching since it causes prebundle dependencies to be cached
|
|
395
|
-
disabled: true, //
|
|
395
|
+
disabled: true, // serverOptions.prebundle === false,
|
|
396
396
|
// Exclude any explicitly defined dependencies (currently build defined externals and node.js built-ins)
|
|
397
397
|
exclude: serverExplicitExternal,
|
|
398
398
|
// Include all implict dependencies from the external packages internal option
|
|
@@ -422,7 +422,7 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
|
|
|
422
422
|
// Browser only optimizeDeps. (This does not run for SSR dependencies).
|
|
423
423
|
optimizeDeps: getDepOptimizationConfig({
|
|
424
424
|
// Only enable with caching since it causes prebundle dependencies to be cached
|
|
425
|
-
disabled:
|
|
425
|
+
disabled: serverOptions.prebundle === false,
|
|
426
426
|
// Exclude any explicitly defined dependencies (currently build defined externals)
|
|
427
427
|
exclude: externalMetadata.explicit,
|
|
428
428
|
// Include all implict dependencies from the external packages internal option
|
|
@@ -62,8 +62,9 @@ function execute(options, context, transforms = {}) {
|
|
|
62
62
|
return (0, build_webpack_1.runWebpack)(config, context, {
|
|
63
63
|
webpackFactory: require('webpack'),
|
|
64
64
|
logging: (stats, config) => {
|
|
65
|
-
if (options.verbose) {
|
|
66
|
-
|
|
65
|
+
if (options.verbose && config.stats !== false) {
|
|
66
|
+
const statsOptions = config.stats === true ? undefined : config.stats;
|
|
67
|
+
context.logger.info(stats.toString(statsOptions));
|
|
67
68
|
}
|
|
68
69
|
},
|
|
69
70
|
}).pipe((0, rxjs_1.concatMap)(async (output) => {
|
|
@@ -162,7 +162,7 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
|
|
|
162
162
|
});
|
|
163
163
|
referencedFileTracker.add(containingFile, Object.keys(workerResult.metafile.inputs).map((input) => path.join(build.initialOptions.absWorkingDir ?? '', input)));
|
|
164
164
|
// Return bundled worker file entry name to be used in the built output
|
|
165
|
-
const workerCodeFile = workerResult.outputFiles.find((file) =>
|
|
165
|
+
const workerCodeFile = workerResult.outputFiles.find((file) => /^worker-[A-Z0-9]{8}.[cm]?js$/.test(path.basename(file.path)));
|
|
166
166
|
(0, node_assert_1.default)(workerCodeFile, 'Web Worker bundled code file should always be present.');
|
|
167
167
|
const workerCodePath = path.relative(build.initialOptions.outdir ?? '', workerCodeFile.path);
|
|
168
168
|
return workerCodePath.replaceAll('\\', '/');
|
|
@@ -53,9 +53,11 @@ function createBrowserCodeBundleOptions(options, target, sourceFileCache) {
|
|
|
53
53
|
}
|
|
54
54
|
if (options.externalPackages) {
|
|
55
55
|
// Package files affected by a customized loader should not be implicitly marked as external
|
|
56
|
-
if (options.loaderExtensions ||
|
|
56
|
+
if (options.loaderExtensions ||
|
|
57
|
+
options.plugins ||
|
|
58
|
+
typeof options.externalPackages === 'object') {
|
|
57
59
|
// Plugin must be added after custom plugins to ensure any added loader options are considered
|
|
58
|
-
buildOptions.plugins?.push((0, external_packages_plugin_1.createExternalPackagesPlugin)());
|
|
60
|
+
buildOptions.plugins?.push((0, external_packages_plugin_1.createExternalPackagesPlugin)(options.externalPackages !== true ? options.externalPackages : undefined));
|
|
59
61
|
}
|
|
60
62
|
else {
|
|
61
63
|
// Safe to use the packages external option directly
|
|
@@ -265,6 +267,7 @@ function getEsBuildCommonOptions(options) {
|
|
|
265
267
|
write: false,
|
|
266
268
|
preserveSymlinks,
|
|
267
269
|
define: {
|
|
270
|
+
...options.define,
|
|
268
271
|
// Only set to false when script optimizations are enabled. It should not be set to true because
|
|
269
272
|
// Angular turns `ngDevMode` into an object for development debugging purposes when not defined
|
|
270
273
|
// which a constant true value would break.
|
|
@@ -162,7 +162,7 @@ class BundlerContext {
|
|
|
162
162
|
// For non-incremental builds, perform a single build
|
|
163
163
|
result = await (0, esbuild_1.build)(this.#esbuildOptions);
|
|
164
164
|
}
|
|
165
|
-
if (this.#
|
|
165
|
+
if (this.#platformIsServer) {
|
|
166
166
|
for (const entry of Object.values(result.metafile.outputs)) {
|
|
167
167
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
168
168
|
entry['ng-platform-server'] = true;
|
|
@@ -232,6 +232,7 @@ class BundlerContext {
|
|
|
232
232
|
name,
|
|
233
233
|
type,
|
|
234
234
|
entrypoint: true,
|
|
235
|
+
serverFile: this.#platformIsServer,
|
|
235
236
|
};
|
|
236
237
|
if (!this.initialFilter || this.initialFilter(record)) {
|
|
237
238
|
initialFiles.set(relativeFilePath, record);
|
|
@@ -251,6 +252,7 @@ class BundlerContext {
|
|
|
251
252
|
type: initialImport.kind === 'import-rule' ? 'style' : 'script',
|
|
252
253
|
entrypoint: false,
|
|
253
254
|
external: initialImport.external,
|
|
255
|
+
serverFile: this.#platformIsServer,
|
|
254
256
|
};
|
|
255
257
|
if (!this.initialFilter || this.initialFilter(record)) {
|
|
256
258
|
initialFiles.set(initialImport.path, record);
|
|
@@ -275,8 +277,7 @@ class BundlerContext {
|
|
|
275
277
|
}
|
|
276
278
|
}
|
|
277
279
|
(0, node_assert_1.default)(this.#esbuildOptions, 'esbuild options cannot be undefined.');
|
|
278
|
-
const {
|
|
279
|
-
const platformIsServer = platform === 'node';
|
|
280
|
+
const { assetNames = '' } = this.#esbuildOptions;
|
|
280
281
|
const mediaDirname = (0, node_path_1.dirname)(assetNames);
|
|
281
282
|
const outputFiles = result.outputFiles.map((file) => {
|
|
282
283
|
let fileType;
|
|
@@ -284,7 +285,9 @@ class BundlerContext {
|
|
|
284
285
|
fileType = BuildOutputFileType.Media;
|
|
285
286
|
}
|
|
286
287
|
else {
|
|
287
|
-
fileType = platformIsServer
|
|
288
|
+
fileType = this.#platformIsServer
|
|
289
|
+
? BuildOutputFileType.Server
|
|
290
|
+
: BuildOutputFileType.Browser;
|
|
288
291
|
}
|
|
289
292
|
return (0, utils_1.convertOutputFile)(file, fileType);
|
|
290
293
|
});
|
|
@@ -294,7 +297,7 @@ class BundlerContext {
|
|
|
294
297
|
outputFiles,
|
|
295
298
|
initialFiles,
|
|
296
299
|
externalImports: {
|
|
297
|
-
[platformIsServer ? 'server' : 'browser']: externalImports,
|
|
300
|
+
[this.#platformIsServer ? 'server' : 'browser']: externalImports,
|
|
298
301
|
},
|
|
299
302
|
externalConfiguration: this.#esbuildOptions.external,
|
|
300
303
|
errors: undefined,
|
|
@@ -314,6 +317,9 @@ class BundlerContext {
|
|
|
314
317
|
}
|
|
315
318
|
}
|
|
316
319
|
}
|
|
320
|
+
get #platformIsServer() {
|
|
321
|
+
return this.#esbuildOptions?.platform === 'node';
|
|
322
|
+
}
|
|
317
323
|
/**
|
|
318
324
|
* Invalidate a stored bundler result based on the previous watch files
|
|
319
325
|
* and a list of changed files.
|
|
@@ -17,22 +17,26 @@ const EXTERNAL_PACKAGE_RESOLUTION = Symbol('EXTERNAL_PACKAGE_RESOLUTION');
|
|
|
17
17
|
*
|
|
18
18
|
* @returns An esbuild plugin.
|
|
19
19
|
*/
|
|
20
|
-
function createExternalPackagesPlugin() {
|
|
20
|
+
function createExternalPackagesPlugin(options) {
|
|
21
|
+
const exclusions = options?.exclude?.length ? new Set(options.exclude) : undefined;
|
|
21
22
|
return {
|
|
22
23
|
name: 'angular-external-packages',
|
|
23
24
|
setup(build) {
|
|
24
|
-
|
|
25
|
-
if
|
|
26
|
-
|
|
25
|
+
const loaderOptionKeys = build.initialOptions.loader && Object.keys(build.initialOptions.loader);
|
|
26
|
+
// Safe to use native packages external option if no loader options or exclusions present
|
|
27
|
+
if (!exclusions && !loaderOptionKeys?.length) {
|
|
27
28
|
build.initialOptions.packages = 'external';
|
|
28
29
|
return;
|
|
29
30
|
}
|
|
30
|
-
const loaderFileExtensions = new Set(
|
|
31
|
+
const loaderFileExtensions = new Set(loaderOptionKeys);
|
|
31
32
|
// Only attempt resolve of non-relative and non-absolute paths
|
|
32
33
|
build.onResolve({ filter: /^[^./]/ }, async (args) => {
|
|
33
34
|
if (args.pluginData?.[EXTERNAL_PACKAGE_RESOLUTION]) {
|
|
34
35
|
return null;
|
|
35
36
|
}
|
|
37
|
+
if (exclusions?.has(args.path)) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
36
40
|
const { importer, kind, resolveDir, namespace, pluginData = {} } = args;
|
|
37
41
|
pluginData[EXTERNAL_PACKAGE_RESOLUTION] = true;
|
|
38
42
|
const result = await build.resolve(args.path, {
|
|
@@ -47,7 +47,7 @@ async function generateIndexHtml(initialFiles, outputFiles, buildOptions, lang)
|
|
|
47
47
|
(0, node_assert_1.default)(indexHtmlOptions, 'indexHtmlOptions cannot be undefined.');
|
|
48
48
|
if (!externalPackages && indexHtmlOptions.preloadInitial) {
|
|
49
49
|
for (const [key, value] of initialFiles) {
|
|
50
|
-
if (value.entrypoint) {
|
|
50
|
+
if (value.entrypoint || value.serverFile) {
|
|
51
51
|
// Entry points are already referenced in the HTML
|
|
52
52
|
continue;
|
|
53
53
|
}
|
|
@@ -94,7 +94,9 @@ async function generateIndexHtml(initialFiles, outputFiles, buildOptions, lang)
|
|
|
94
94
|
baseHref,
|
|
95
95
|
lang,
|
|
96
96
|
outputPath: virtualOutputPath,
|
|
97
|
-
files: [...initialFiles]
|
|
97
|
+
files: [...initialFiles]
|
|
98
|
+
.filter(([, file]) => !file.serverFile)
|
|
99
|
+
.map(([file, record]) => ({
|
|
98
100
|
name: record.name ?? '',
|
|
99
101
|
file,
|
|
100
102
|
extension: node_path_1.default.extname(file),
|
|
@@ -99,6 +99,19 @@ function createAngularMemoryPlugin(options) {
|
|
|
99
99
|
next();
|
|
100
100
|
return;
|
|
101
101
|
}
|
|
102
|
+
// HTML fallbacking
|
|
103
|
+
// This matches what happens in the vite html fallback middleware.
|
|
104
|
+
// ref: https://github.com/vitejs/vite/blob/main/packages/vite/src/node/server/middlewares/htmlFallback.ts#L9
|
|
105
|
+
const htmlAssetSourcePath = pathname[pathname.length - 1] === '/'
|
|
106
|
+
? // Trailing slash check for `index.html`.
|
|
107
|
+
assets.get(pathname + 'index.html')
|
|
108
|
+
: // Non-trailing slash check for fallback `.html`
|
|
109
|
+
assets.get(pathname + '.html');
|
|
110
|
+
if (htmlAssetSourcePath) {
|
|
111
|
+
req.url = `${server.config.base}@fs/${encodeURI(htmlAssetSourcePath)}`;
|
|
112
|
+
next();
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
102
115
|
// Resource files are handled directly.
|
|
103
116
|
// Global stylesheets (CSS files) are currently considered resources to workaround
|
|
104
117
|
// dev server sourcemap issues with stylesheets.
|
|
@@ -419,8 +419,9 @@ function createWebpackLoggingCallback(options, logger) {
|
|
|
419
419
|
...(0, helpers_1.normalizeExtraEntryPoints)(scripts, 'scripts'),
|
|
420
420
|
];
|
|
421
421
|
return (stats, config) => {
|
|
422
|
-
if (verbose) {
|
|
423
|
-
|
|
422
|
+
if (verbose && config.stats !== false) {
|
|
423
|
+
const statsOptions = config.stats === true ? undefined : config.stats;
|
|
424
|
+
logger.info(stats.toString(statsOptions));
|
|
424
425
|
}
|
|
425
426
|
const rawStats = stats.toJson((0, helpers_1.getStatsOptions)(false));
|
|
426
427
|
const webpackStats = {
|