@angular/build 20.0.0-next.2 → 20.0.0-next.4
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 +12 -9
- package/src/builders/application/index.js +13 -1
- package/src/builders/application/options.d.ts +2 -0
- package/src/builders/application/options.js +30 -7
- package/src/builders/application/schema.d.ts +19 -5
- package/src/builders/application/schema.json +13 -2
- package/src/builders/application/setup-bundling.js +1 -0
- package/src/builders/dev-server/vite-server.js +0 -6
- package/src/builders/karma/application_builder.js +17 -1
- package/src/builders/karma/index.js +1 -1
- package/src/builders/karma/polyfills/init_test_bed.js +2 -5
- package/src/tools/esbuild/application-code-bundle.js +26 -7
- package/src/tools/esbuild/global-styles.js +1 -0
- package/src/tools/esbuild/javascript-transformer-worker.js +1 -3
- package/src/tools/esbuild/stylesheets/bundle-options.d.ts +1 -0
- package/src/tools/esbuild/stylesheets/bundle-options.js +1 -0
- package/src/tools/esbuild/utils.js +1 -1
- package/src/tools/vite/middlewares/ssr-middleware.js +5 -4
- package/src/utils/normalize-cache.js +1 -1
- package/src/utils/normalize-source-maps.js +2 -0
- package/src/utils/server-rendering/launch-server.js +1 -1
- package/src/utils/server-rendering/prerender.js +3 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angular/build",
|
|
3
|
-
"version": "20.0.0-next.
|
|
3
|
+
"version": "20.0.0-next.4",
|
|
4
4
|
"description": "Official build system for Angular",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Angular CLI",
|
|
@@ -23,16 +23,15 @@
|
|
|
23
23
|
"builders": "builders.json",
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@ampproject/remapping": "2.3.0",
|
|
26
|
-
"@angular-devkit/architect": "0.2000.0-next.
|
|
26
|
+
"@angular-devkit/architect": "0.2000.0-next.4",
|
|
27
27
|
"@babel/core": "7.26.10",
|
|
28
28
|
"@babel/helper-annotate-as-pure": "7.25.9",
|
|
29
29
|
"@babel/helper-split-export-declaration": "7.24.7",
|
|
30
|
-
"@babel/plugin-syntax-import-attributes": "7.26.0",
|
|
31
30
|
"@inquirer/confirm": "5.1.8",
|
|
32
31
|
"@vitejs/plugin-basic-ssl": "2.0.0",
|
|
33
32
|
"beasties": "0.2.0",
|
|
34
33
|
"browserslist": "^4.23.0",
|
|
35
|
-
"esbuild": "0.25.
|
|
34
|
+
"esbuild": "0.25.2",
|
|
36
35
|
"https-proxy-agent": "7.0.6",
|
|
37
36
|
"istanbul-lib-instrument": "6.0.3",
|
|
38
37
|
"jsonc-parser": "3.3.1",
|
|
@@ -42,12 +41,12 @@
|
|
|
42
41
|
"parse5-html-rewriting-stream": "7.0.0",
|
|
43
42
|
"picomatch": "4.0.2",
|
|
44
43
|
"piscina": "4.9.2",
|
|
45
|
-
"rollup": "4.
|
|
46
|
-
"sass": "1.86.
|
|
44
|
+
"rollup": "4.39.0",
|
|
45
|
+
"sass": "1.86.1",
|
|
47
46
|
"semver": "7.7.1",
|
|
48
47
|
"source-map-support": "0.5.21",
|
|
49
48
|
"tinyglobby": "0.2.12",
|
|
50
|
-
"vite": "6.2.
|
|
49
|
+
"vite": "6.2.4",
|
|
51
50
|
"watchpack": "2.4.2"
|
|
52
51
|
},
|
|
53
52
|
"optionalDependencies": {
|
|
@@ -57,9 +56,10 @@
|
|
|
57
56
|
"@angular/compiler": "^20.0.0 || ^20.0.0-next.0",
|
|
58
57
|
"@angular/compiler-cli": "^20.0.0 || ^20.0.0-next.0",
|
|
59
58
|
"@angular/localize": "^20.0.0 || ^20.0.0-next.0",
|
|
59
|
+
"@angular/platform-browser": "^20.0.0 || ^20.0.0-next.0",
|
|
60
60
|
"@angular/platform-server": "^20.0.0 || ^20.0.0-next.0",
|
|
61
61
|
"@angular/service-worker": "^20.0.0 || ^20.0.0-next.0",
|
|
62
|
-
"@angular/ssr": "^20.0.0-next.
|
|
62
|
+
"@angular/ssr": "^20.0.0-next.4",
|
|
63
63
|
"karma": "^6.4.0",
|
|
64
64
|
"less": "^4.2.0",
|
|
65
65
|
"ng-packagr": "^20.0.0 || ^20.0.0-next.0",
|
|
@@ -71,6 +71,9 @@
|
|
|
71
71
|
"@angular/localize": {
|
|
72
72
|
"optional": true
|
|
73
73
|
},
|
|
74
|
+
"@angular/platform-browser": {
|
|
75
|
+
"optional": true
|
|
76
|
+
},
|
|
74
77
|
"@angular/platform-server": {
|
|
75
78
|
"optional": true
|
|
76
79
|
},
|
|
@@ -102,7 +105,7 @@
|
|
|
102
105
|
},
|
|
103
106
|
"packageManager": "pnpm@9.15.6",
|
|
104
107
|
"engines": {
|
|
105
|
-
"node": "^20.11.1 || >=22.
|
|
108
|
+
"node": "^20.11.1 || >=22.11.0",
|
|
106
109
|
"npm": "^6.11.0 || ^7.5.6 || >=8.0.0",
|
|
107
110
|
"yarn": ">= 1.13.0"
|
|
108
111
|
},
|
|
@@ -27,6 +27,7 @@ const build_action_1 = require("./build-action");
|
|
|
27
27
|
const execute_build_1 = require("./execute-build");
|
|
28
28
|
const options_1 = require("./options");
|
|
29
29
|
const results_1 = require("./results");
|
|
30
|
+
const isNodeV22orHigher = Number(process.versions.node.split('.', 1)[0]) >= 22;
|
|
30
31
|
async function* buildApplicationInternal(options,
|
|
31
32
|
// TODO: Integrate abort signal support into builder system
|
|
32
33
|
context, extensions) {
|
|
@@ -162,7 +163,18 @@ async function* buildApplication(options, context, extensions) {
|
|
|
162
163
|
}
|
|
163
164
|
else {
|
|
164
165
|
// Copy file contents
|
|
165
|
-
|
|
166
|
+
if (isNodeV22orHigher) {
|
|
167
|
+
// Use newer `cp` API on Node.js 22+ (minimum v22 for CLI is 22.11)
|
|
168
|
+
await promises_1.default.cp(file.inputPath, fullFilePath, {
|
|
169
|
+
mode: promises_1.default.constants.COPYFILE_FICLONE,
|
|
170
|
+
preserveTimestamps: true,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
// For Node.js 20 use `copyFile` (`cp` is not stable for v20)
|
|
175
|
+
// TODO: Remove when Node.js 20 is no longer supported
|
|
176
|
+
await promises_1.default.copyFile(file.inputPath, fullFilePath, promises_1.default.constants.COPYFILE_FICLONE);
|
|
177
|
+
}
|
|
166
178
|
}
|
|
167
179
|
});
|
|
168
180
|
// Delete any removed files if incremental
|
|
@@ -203,6 +203,8 @@ export declare function normalizeOptions(context: BuilderContext, projectName: s
|
|
|
203
203
|
};
|
|
204
204
|
templateUpdates: boolean;
|
|
205
205
|
incrementalResults: boolean;
|
|
206
|
+
customConditions: string[] | undefined;
|
|
207
|
+
frameworkVersion: string;
|
|
206
208
|
}>;
|
|
207
209
|
export declare function getLocaleBaseHref(baseHref: string | undefined, i18n: NormalizedApplicationBuildOptions['i18nOptions'], locale: string): string | undefined;
|
|
208
210
|
export {};
|
|
@@ -132,12 +132,12 @@ async function normalizeOptions(context, projectName, options, extensions) {
|
|
|
132
132
|
? undefined
|
|
133
133
|
: await getTailwindConfig(searchDirectories, workspaceRoot, context);
|
|
134
134
|
let serverEntryPoint;
|
|
135
|
-
if (options.server) {
|
|
135
|
+
if (typeof options.server === 'string') {
|
|
136
|
+
if (options.server === '') {
|
|
137
|
+
throw new Error('The "server" option cannot be an empty string.');
|
|
138
|
+
}
|
|
136
139
|
serverEntryPoint = node_path_1.default.join(workspaceRoot, options.server);
|
|
137
140
|
}
|
|
138
|
-
else if (options.server === '') {
|
|
139
|
-
throw new Error('The "server" option cannot be an empty string.');
|
|
140
|
-
}
|
|
141
141
|
let prerenderOptions;
|
|
142
142
|
if (options.prerender) {
|
|
143
143
|
const { discoverRoutes = true, routesFile = undefined } = options.prerender === true ? {} : options.prerender;
|
|
@@ -163,7 +163,7 @@ async function normalizeOptions(context, projectName, options, extensions) {
|
|
|
163
163
|
route: 'shell',
|
|
164
164
|
};
|
|
165
165
|
}
|
|
166
|
-
const outputPath = options.outputPath;
|
|
166
|
+
const outputPath = options.outputPath ?? node_path_1.default.join(workspaceRoot, 'dist', projectName);
|
|
167
167
|
const outputOptions = {
|
|
168
168
|
browser: 'browser',
|
|
169
169
|
server: 'server',
|
|
@@ -191,12 +191,18 @@ async function normalizeOptions(context, projectName, options, extensions) {
|
|
|
191
191
|
let indexHtmlOptions;
|
|
192
192
|
// index can never have a value of `true` but in the schema it's of type `boolean`.
|
|
193
193
|
if (typeof options.index !== 'boolean') {
|
|
194
|
+
let indexInput;
|
|
194
195
|
let indexOutput;
|
|
195
196
|
// The output file will be created within the configured output path
|
|
196
197
|
if (typeof options.index === 'string') {
|
|
197
|
-
indexOutput = options.index;
|
|
198
|
+
indexInput = indexOutput = node_path_1.default.join(workspaceRoot, options.index);
|
|
199
|
+
}
|
|
200
|
+
else if (typeof options.index === 'undefined') {
|
|
201
|
+
indexInput = node_path_1.default.join(projectSourceRoot, 'index.html');
|
|
202
|
+
indexOutput = 'index.html';
|
|
198
203
|
}
|
|
199
204
|
else {
|
|
205
|
+
indexInput = node_path_1.default.join(workspaceRoot, options.index.input);
|
|
200
206
|
indexOutput = options.index.output || 'index.html';
|
|
201
207
|
}
|
|
202
208
|
/**
|
|
@@ -214,7 +220,7 @@ async function normalizeOptions(context, projectName, options, extensions) {
|
|
|
214
220
|
? exports.INDEX_HTML_CSR
|
|
215
221
|
: indexBaseName;
|
|
216
222
|
indexHtmlOptions = {
|
|
217
|
-
input:
|
|
223
|
+
input: indexInput,
|
|
218
224
|
output: indexOutput,
|
|
219
225
|
insertionOrder: [
|
|
220
226
|
['polyfills', true],
|
|
@@ -312,6 +318,8 @@ async function normalizeOptions(context, projectName, options, extensions) {
|
|
|
312
318
|
security,
|
|
313
319
|
templateUpdates: !!options.templateUpdates,
|
|
314
320
|
incrementalResults: !!options.incrementalResults,
|
|
321
|
+
customConditions: options.conditions,
|
|
322
|
+
frameworkVersion: await findFrameworkVersion(projectRoot),
|
|
315
323
|
};
|
|
316
324
|
}
|
|
317
325
|
async function getTailwindConfig(searchDirectories, workspaceRoot, context) {
|
|
@@ -470,3 +478,18 @@ function normalizeExternals(value) {
|
|
|
470
478
|
}
|
|
471
479
|
return [...new Set(value.map((d) => (d.endsWith('/*') ? d.slice(0, -2) : d)))];
|
|
472
480
|
}
|
|
481
|
+
async function findFrameworkVersion(projectRoot) {
|
|
482
|
+
// Create a custom require function for ESM compliance.
|
|
483
|
+
// NOTE: The trailing slash is significant.
|
|
484
|
+
const projectResolve = (0, node_module_1.createRequire)(projectRoot + '/').resolve;
|
|
485
|
+
try {
|
|
486
|
+
const manifestPath = projectResolve('@angular/core/package.json');
|
|
487
|
+
const manifestData = await (0, promises_1.readFile)(manifestPath, 'utf-8');
|
|
488
|
+
const manifestObject = JSON.parse(manifestData);
|
|
489
|
+
const version = manifestObject.version;
|
|
490
|
+
return version;
|
|
491
|
+
}
|
|
492
|
+
catch {
|
|
493
|
+
throw new Error('Error: It appears that "@angular/core" is missing as a dependency. Please ensure it is included in your project.');
|
|
494
|
+
}
|
|
495
|
+
}
|
|
@@ -37,6 +37,13 @@ export type Schema = {
|
|
|
37
37
|
* Automatically clear the terminal screen during rebuilds.
|
|
38
38
|
*/
|
|
39
39
|
clearScreen?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Custom package resolution conditions used to resolve conditional exports/imports.
|
|
42
|
+
* Defaults to ['module', 'development'/'production']. The following special conditions are
|
|
43
|
+
* always present if the requirements are satisfied: 'default', 'import', 'require',
|
|
44
|
+
* 'browser', 'node'.
|
|
45
|
+
*/
|
|
46
|
+
conditions?: string[];
|
|
40
47
|
/**
|
|
41
48
|
* Define the crossorigin attribute setting of elements that provide CORS support.
|
|
42
49
|
*/
|
|
@@ -86,7 +93,7 @@ export type Schema = {
|
|
|
86
93
|
/**
|
|
87
94
|
* Configures the generation of the application's HTML index.
|
|
88
95
|
*/
|
|
89
|
-
index
|
|
96
|
+
index?: IndexUnion;
|
|
90
97
|
/**
|
|
91
98
|
* The stylesheet language to use for the application's inline component styles.
|
|
92
99
|
*/
|
|
@@ -128,7 +135,7 @@ export type Schema = {
|
|
|
128
135
|
/**
|
|
129
136
|
* Specify the output path relative to workspace root.
|
|
130
137
|
*/
|
|
131
|
-
outputPath
|
|
138
|
+
outputPath?: OutputPathUnion;
|
|
132
139
|
/**
|
|
133
140
|
* Enable and define the file watching poll time period in milliseconds.
|
|
134
141
|
*/
|
|
@@ -163,11 +170,11 @@ export type Schema = {
|
|
|
163
170
|
* The full path for the server entry point to the application, relative to the current
|
|
164
171
|
* workspace.
|
|
165
172
|
*/
|
|
166
|
-
server?:
|
|
173
|
+
server?: Serv;
|
|
167
174
|
/**
|
|
168
175
|
* Generates a service worker configuration.
|
|
169
176
|
*/
|
|
170
|
-
serviceWorker?:
|
|
177
|
+
serviceWorker?: Serv;
|
|
171
178
|
/**
|
|
172
179
|
* Output source maps for scripts and styles. For more information, see
|
|
173
180
|
* https://angular.dev/reference/configs/workspace-config#source-map-configuration.
|
|
@@ -496,9 +503,12 @@ export type AutoCspClass = {
|
|
|
496
503
|
unsafeEval?: boolean;
|
|
497
504
|
};
|
|
498
505
|
/**
|
|
506
|
+
* The full path for the server entry point to the application, relative to the current
|
|
507
|
+
* workspace.
|
|
508
|
+
*
|
|
499
509
|
* Generates a service worker configuration.
|
|
500
510
|
*/
|
|
501
|
-
export type
|
|
511
|
+
export type Serv = boolean | string;
|
|
502
512
|
/**
|
|
503
513
|
* Output source maps for scripts and styles. For more information, see
|
|
504
514
|
* https://angular.dev/reference/configs/workspace-config#source-map-configuration.
|
|
@@ -513,6 +523,10 @@ export type SourceMapClass = {
|
|
|
513
523
|
* Output source maps for all scripts.
|
|
514
524
|
*/
|
|
515
525
|
scripts?: boolean;
|
|
526
|
+
/**
|
|
527
|
+
* Output original source content for files within the source map.
|
|
528
|
+
*/
|
|
529
|
+
sourcesContent?: boolean;
|
|
516
530
|
/**
|
|
517
531
|
* Output source maps for all styles.
|
|
518
532
|
*/
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
"description": "The full path for the browser entry point to the application, relative to the current workspace."
|
|
18
18
|
},
|
|
19
19
|
"server": {
|
|
20
|
-
"type": "string",
|
|
21
20
|
"description": "The full path for the server entry point to the application, relative to the current workspace.",
|
|
22
21
|
"oneOf": [
|
|
23
22
|
{
|
|
@@ -293,6 +292,13 @@
|
|
|
293
292
|
"type": "string"
|
|
294
293
|
}
|
|
295
294
|
},
|
|
295
|
+
"conditions": {
|
|
296
|
+
"description": "Custom package resolution conditions used to resolve conditional exports/imports. Defaults to ['module', 'development'/'production']. The following special conditions are always present if the requirements are satisfied: 'default', 'import', 'require', 'browser', 'node'.",
|
|
297
|
+
"type": "array",
|
|
298
|
+
"items": {
|
|
299
|
+
"type": "string"
|
|
300
|
+
}
|
|
301
|
+
},
|
|
296
302
|
"fileReplacements": {
|
|
297
303
|
"description": "Replace compilation source files with other compilation source files in the build.",
|
|
298
304
|
"type": "array",
|
|
@@ -370,6 +376,11 @@
|
|
|
370
376
|
"type": "boolean",
|
|
371
377
|
"description": "Resolve vendor packages source maps.",
|
|
372
378
|
"default": false
|
|
379
|
+
},
|
|
380
|
+
"sourcesContent": {
|
|
381
|
+
"type": "boolean",
|
|
382
|
+
"description": "Output original source content for files within the source map.",
|
|
383
|
+
"default": true
|
|
373
384
|
}
|
|
374
385
|
},
|
|
375
386
|
"additionalProperties": false
|
|
@@ -605,7 +616,7 @@
|
|
|
605
616
|
}
|
|
606
617
|
},
|
|
607
618
|
"additionalProperties": false,
|
|
608
|
-
"required": ["
|
|
619
|
+
"required": ["browser", "tsConfig"],
|
|
609
620
|
"definitions": {
|
|
610
621
|
"assetPattern": {
|
|
611
622
|
"oneOf": [
|
|
@@ -86,6 +86,7 @@ function createComponentStyleBundler(options, target) {
|
|
|
86
86
|
// the same as being disabled. Disabling has the advantage of avoiding the overhead
|
|
87
87
|
// of sourcemap processing.
|
|
88
88
|
sourcemapOptions.styles && !sourcemapOptions.hidden ? 'linked' : false,
|
|
89
|
+
sourcesContent: sourcemapOptions.sourcesContent,
|
|
89
90
|
outputNames,
|
|
90
91
|
includePaths: stylePreprocessorOptions?.includePaths,
|
|
91
92
|
// string[] | undefined' is not assignable to type '(Version | DeprecationOrId)[] | undefined'.
|
|
@@ -121,12 +121,6 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
|
|
|
121
121
|
// This will also replace file-based/inline styles as code if external runtime styles are not enabled.
|
|
122
122
|
browserOptions.templateUpdates =
|
|
123
123
|
serverOptions.liveReload && serverOptions.hmr && environment_options_1.useComponentTemplateHmr;
|
|
124
|
-
if (browserOptions.templateUpdates) {
|
|
125
|
-
context.logger.warn('Component HMR has been enabled.\n' +
|
|
126
|
-
'If you encounter application reload issues, you can manually reload the page to bypass HMR and/or disable this feature with the' +
|
|
127
|
-
' `--no-hmr` command line option.\n' +
|
|
128
|
-
'Please consider reporting any issues you encounter here: https://github.com/angular/angular-cli/issues\n');
|
|
129
|
-
}
|
|
130
124
|
browserOptions.incrementalResults = true;
|
|
131
125
|
// Setup the prebundling transformer that will be shared across Vite prebundling requests
|
|
132
126
|
const prebundleTransformer = new internal_1.JavaScriptTransformer(
|
|
@@ -54,6 +54,7 @@ const results_1 = require("../application/results");
|
|
|
54
54
|
const schema_1 = require("../application/schema");
|
|
55
55
|
const find_tests_1 = require("./find-tests");
|
|
56
56
|
const localResolve = (0, node_module_1.createRequire)(__filename).resolve;
|
|
57
|
+
const isWindows = process.platform === 'win32';
|
|
57
58
|
class ApplicationBuildError extends Error {
|
|
58
59
|
constructor(message) {
|
|
59
60
|
super(message);
|
|
@@ -74,7 +75,13 @@ class AngularAssetsMiddleware {
|
|
|
74
75
|
let err = null;
|
|
75
76
|
try {
|
|
76
77
|
const url = new URL(`http://${req.headers['host']}${req.url}`);
|
|
77
|
-
|
|
78
|
+
// Remove the leading slash from the URL path and convert to platform specific.
|
|
79
|
+
// The latest build files will use the platform path separator.
|
|
80
|
+
let pathname = url.pathname.slice(1);
|
|
81
|
+
if (isWindows) {
|
|
82
|
+
pathname = pathname.replaceAll(path.posix.sep, path.win32.sep);
|
|
83
|
+
}
|
|
84
|
+
const file = this.latestBuildFiles.files[pathname];
|
|
78
85
|
if (file?.origin === 'disk') {
|
|
79
86
|
this.serveFile(file.inputPath, undefined, res);
|
|
80
87
|
return;
|
|
@@ -288,6 +295,7 @@ async function collectEntrypoints(options, context, projectSourceRoot) {
|
|
|
288
295
|
const testFiles = await (0, find_tests_1.findTests)(options.include ?? [], options.exclude ?? [], context.workspaceRoot, projectSourceRoot);
|
|
289
296
|
return (0, find_tests_1.getTestEntrypoints)(testFiles, { projectSourceRoot, workspaceRoot: context.workspaceRoot });
|
|
290
297
|
}
|
|
298
|
+
// eslint-disable-next-line max-lines-per-function
|
|
291
299
|
async function initializeApplication(options, context, karmaOptions, transforms = {}) {
|
|
292
300
|
const outputPath = path.join(context.workspaceRoot, 'dist/test-out', (0, node_crypto_1.randomUUID)());
|
|
293
301
|
const projectSourceRoot = await getProjectSourceRoot(context);
|
|
@@ -399,6 +407,14 @@ async function initializeApplication(options, context, karmaOptions, transforms
|
|
|
399
407
|
karmaOptions.files.push({ pattern: `*.css`, type: 'css', watched: false });
|
|
400
408
|
}
|
|
401
409
|
const parsedKarmaConfig = await karma.config.parseConfig(options.karmaConfig && path.resolve(context.workspaceRoot, options.karmaConfig), transforms.karmaOptions ? transforms.karmaOptions(karmaOptions) : karmaOptions, { promiseConfig: true, throwErrors: true });
|
|
410
|
+
// Check for jsdom which does not support executing ESM scripts.
|
|
411
|
+
// If present, remove jsdom and issue a warning.
|
|
412
|
+
const updatedBrowsers = parsedKarmaConfig.browsers?.filter((browser) => browser !== 'jsdom');
|
|
413
|
+
if (parsedKarmaConfig.browsers?.length !== updatedBrowsers?.length) {
|
|
414
|
+
parsedKarmaConfig.browsers = updatedBrowsers;
|
|
415
|
+
context.logger.warn(`'jsdom' does not support ESM code execution and cannot be used for karma testing.` +
|
|
416
|
+
` The 'jsdom' entry has been removed from the 'browsers' option.`);
|
|
417
|
+
}
|
|
402
418
|
// Remove the webpack plugin/framework:
|
|
403
419
|
// Alternative would be to make the Karma plugin "smart" but that's a tall order
|
|
404
420
|
// with managing unneeded imports etc..
|
|
@@ -76,7 +76,7 @@ function getBaseKarmaOptions(options, context) {
|
|
|
76
76
|
karmaOptions.client.clearContext ??= singleRun ?? false; // `singleRun` defaults to `false` per Karma docs.
|
|
77
77
|
// Convert browsers from a string to an array
|
|
78
78
|
if (typeof options.browsers === 'string' && options.browsers) {
|
|
79
|
-
karmaOptions.browsers = options.browsers.split(',');
|
|
79
|
+
karmaOptions.browsers = options.browsers.split(',').map((browser) => browser.trim());
|
|
80
80
|
}
|
|
81
81
|
else if (options.browsers === false) {
|
|
82
82
|
karmaOptions.browsers = [];
|
|
@@ -7,13 +7,10 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { getTestBed } from '@angular/core/testing';
|
|
10
|
-
import {
|
|
11
|
-
BrowserDynamicTestingModule,
|
|
12
|
-
platformBrowserDynamicTesting,
|
|
13
|
-
} from '@angular/platform-browser-dynamic/testing';
|
|
10
|
+
import { BrowserTestingModule, platformBrowserTesting } from '@angular/platform-browser/testing';
|
|
14
11
|
|
|
15
12
|
// Initialize the Angular testing environment.
|
|
16
|
-
getTestBed().initTestEnvironment(
|
|
13
|
+
getTestBed().initTestEnvironment(BrowserTestingModule, platformBrowserTesting(), {
|
|
17
14
|
errorOnUnknownElements: true,
|
|
18
15
|
errorOnUnknownProperties: true,
|
|
19
16
|
});
|
|
@@ -382,7 +382,7 @@ function getEsBuildServerCommonOptions(options) {
|
|
|
382
382
|
};
|
|
383
383
|
}
|
|
384
384
|
function getEsBuildCommonOptions(options) {
|
|
385
|
-
const { workspaceRoot, outExtension, optimizationOptions, sourcemapOptions, tsconfig, externalDependencies, outputNames, preserveSymlinks, jit, loaderExtensions, jsonLogs, i18nOptions, } = options;
|
|
385
|
+
const { workspaceRoot, outExtension, optimizationOptions, sourcemapOptions, tsconfig, externalDependencies, outputNames, preserveSymlinks, jit, loaderExtensions, jsonLogs, i18nOptions, customConditions, frameworkVersion, } = options;
|
|
386
386
|
// Ensure unique hashes for i18n translation changes when using post-process inlining.
|
|
387
387
|
// This hash value is added as a footer to each file and ensures that the output file names (with hashes)
|
|
388
388
|
// change when translation files have changed. If this is not done the post processed files may have
|
|
@@ -393,18 +393,36 @@ function getEsBuildCommonOptions(options) {
|
|
|
393
393
|
const i18nHash = Object.values(i18nOptions.locales).reduce((data, locale) => data + locale.files.map((file) => file.integrity || '').join('|'), '');
|
|
394
394
|
footer = { js: `/**i18n:${(0, node_crypto_1.createHash)('sha256').update(i18nHash).digest('hex')}*/` };
|
|
395
395
|
}
|
|
396
|
+
// Core conditions that are always included
|
|
397
|
+
const conditions = [
|
|
398
|
+
// Required to support rxjs 7.x which will use es5 code if this condition is not present
|
|
399
|
+
'es2015',
|
|
400
|
+
'es2020',
|
|
401
|
+
];
|
|
402
|
+
// The pre-linked code is not used with JIT for two reasons:
|
|
403
|
+
// 1) The pre-linked code may not have the metadata included that is required for JIT
|
|
404
|
+
// 2) The CLI is otherwise setup to use runtime linking for JIT to match the application template compilation
|
|
405
|
+
if (!jit) {
|
|
406
|
+
// The pre-linked package condition is based on the framework version.
|
|
407
|
+
// Currently this is specific to each patch version of the framework.
|
|
408
|
+
conditions.push('angular:linked-' + frameworkVersion);
|
|
409
|
+
}
|
|
410
|
+
// Append custom conditions if present
|
|
411
|
+
if (customConditions) {
|
|
412
|
+
conditions.push(...customConditions);
|
|
413
|
+
}
|
|
414
|
+
else {
|
|
415
|
+
// Include default conditions
|
|
416
|
+
conditions.push('module');
|
|
417
|
+
conditions.push(optimizationOptions.scripts ? 'production' : 'development');
|
|
418
|
+
}
|
|
396
419
|
return {
|
|
397
420
|
absWorkingDir: workspaceRoot,
|
|
398
421
|
format: 'esm',
|
|
399
422
|
bundle: true,
|
|
400
423
|
packages: 'bundle',
|
|
401
424
|
assetNames: outputNames.media,
|
|
402
|
-
conditions
|
|
403
|
-
'es2020',
|
|
404
|
-
'es2015',
|
|
405
|
-
'module',
|
|
406
|
-
optimizationOptions.scripts ? 'production' : 'development',
|
|
407
|
-
],
|
|
425
|
+
conditions,
|
|
408
426
|
resolveExtensions: ['.ts', '.tsx', '.mjs', '.js', '.cjs'],
|
|
409
427
|
metafile: true,
|
|
410
428
|
legalComments: options.extractLicenses ? 'none' : 'eof',
|
|
@@ -416,6 +434,7 @@ function getEsBuildCommonOptions(options) {
|
|
|
416
434
|
outdir: workspaceRoot,
|
|
417
435
|
outExtension: outExtension ? { '.js': `.${outExtension}` } : undefined,
|
|
418
436
|
sourcemap: sourcemapOptions.scripts && (sourcemapOptions.hidden ? 'external' : true),
|
|
437
|
+
sourcesContent: sourcemapOptions.sourcesContent,
|
|
419
438
|
splitting: true,
|
|
420
439
|
chunkNames: options.namedChunks ? '[name]-[hash]' : 'chunk-[hash]',
|
|
421
440
|
tsconfig,
|
|
@@ -35,6 +35,7 @@ function createGlobalStylesBundleOptions(options, target, initial) {
|
|
|
35
35
|
optimization: !!optimizationOptions.styles.minify,
|
|
36
36
|
inlineFonts: !!optimizationOptions.fonts.inline,
|
|
37
37
|
sourcemap: !!sourcemapOptions.styles && (sourcemapOptions.hidden ? 'external' : true),
|
|
38
|
+
sourcesContent: sourcemapOptions.sourcesContent,
|
|
38
39
|
preserveSymlinks,
|
|
39
40
|
target,
|
|
40
41
|
externalDependencies,
|
|
@@ -70,9 +70,7 @@ async function transformWithBabel(filename, data, options) {
|
|
|
70
70
|
const shouldLink = !options.skipLinker && (await requiresLinking(filename, data));
|
|
71
71
|
const useInputSourcemap = options.sourcemap &&
|
|
72
72
|
(!!options.thirdPartySourcemaps || !/[\\/]node_modules[\\/]/.test(filename));
|
|
73
|
-
|
|
74
|
-
const { default: importAttributePlugin } = await Promise.resolve().then(() => __importStar(require('@babel/plugin-syntax-import-attributes')));
|
|
75
|
-
const plugins = [importAttributePlugin];
|
|
73
|
+
const plugins = [];
|
|
76
74
|
if (options.instrumentForCoverage) {
|
|
77
75
|
const { default: coveragePlugin } = await Promise.resolve().then(() => __importStar(require('../babel/plugins/add-code-coverage.js')));
|
|
78
76
|
plugins.push(coveragePlugin);
|
|
@@ -47,6 +47,7 @@ function createStylesheetBundleOptions(options, cache, inlineComponentData) {
|
|
|
47
47
|
minify: options.optimization,
|
|
48
48
|
metafile: true,
|
|
49
49
|
sourcemap: options.sourcemap,
|
|
50
|
+
sourcesContent: options.sourcesContent,
|
|
50
51
|
outdir: options.workspaceRoot,
|
|
51
52
|
write: false,
|
|
52
53
|
platform: 'browser',
|
|
@@ -315,7 +315,7 @@ function transformSupportedBrowsersToTargets(supportedBrowsers) {
|
|
|
315
315
|
}
|
|
316
316
|
return transformed;
|
|
317
317
|
}
|
|
318
|
-
const SUPPORTED_NODE_VERSIONS = '^20.11.1 || >=22.
|
|
318
|
+
const SUPPORTED_NODE_VERSIONS = '^20.11.1 || >=22.11.0';
|
|
319
319
|
/**
|
|
320
320
|
* Transform supported Node.js versions to esbuild target.
|
|
321
321
|
* @see https://esbuild.github.io/api/#target
|
|
@@ -22,11 +22,12 @@ function createAngularSsrInternalMiddleware(server, indexHtmlTransformer) {
|
|
|
22
22
|
// which must be processed by the runtime linker, even if they are not used.
|
|
23
23
|
await (0, load_esm_1.loadEsmModule)('@angular/compiler');
|
|
24
24
|
const { writeResponseToNodeResponse, createWebRequestFromNodeRequest } = await (0, load_esm_1.loadEsmModule)('@angular/ssr/node');
|
|
25
|
-
// The following is necessary because accessing the module after invalidation may result in an empty module,
|
|
26
|
-
// which can trigger a `TypeError: ɵgetOrCreateAngularServerApp is not a function` error.
|
|
27
|
-
// TODO: look into why.
|
|
28
|
-
await server.ssrLoadModule('/main.server.mjs');
|
|
29
25
|
const { ɵgetOrCreateAngularServerApp } = (await server.ssrLoadModule('/main.server.mjs'));
|
|
26
|
+
// `ɵgetOrCreateAngularServerApp` can be undefined right after an error.
|
|
27
|
+
// See: https://github.com/angular/angular-cli/issues/29907
|
|
28
|
+
if (!ɵgetOrCreateAngularServerApp) {
|
|
29
|
+
return next();
|
|
30
|
+
}
|
|
30
31
|
const angularServerApp = ɵgetOrCreateAngularServerApp({
|
|
31
32
|
allowStaticRouteRender: true,
|
|
32
33
|
});
|
|
@@ -10,7 +10,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
10
10
|
exports.normalizeCacheOptions = normalizeCacheOptions;
|
|
11
11
|
const node_path_1 = require("node:path");
|
|
12
12
|
/** Version placeholder is replaced during the build process with actual package version */
|
|
13
|
-
const VERSION = '20.0.0-next.
|
|
13
|
+
const VERSION = '20.0.0-next.4';
|
|
14
14
|
function hasCacheMetadata(value) {
|
|
15
15
|
return (!!value &&
|
|
16
16
|
typeof value === 'object' &&
|
|
@@ -13,10 +13,12 @@ function normalizeSourceMaps(sourceMap) {
|
|
|
13
13
|
const styles = typeof sourceMap === 'object' ? sourceMap.styles : sourceMap;
|
|
14
14
|
const hidden = (typeof sourceMap === 'object' && sourceMap.hidden) || false;
|
|
15
15
|
const vendor = (typeof sourceMap === 'object' && sourceMap.vendor) || false;
|
|
16
|
+
const sourcesContent = typeof sourceMap === 'object' ? sourceMap.sourcesContent : sourceMap;
|
|
16
17
|
return {
|
|
17
18
|
vendor,
|
|
18
19
|
hidden,
|
|
19
20
|
scripts,
|
|
20
21
|
styles,
|
|
22
|
+
sourcesContent,
|
|
21
23
|
};
|
|
22
24
|
}
|
|
@@ -54,7 +54,7 @@ async function prerenderPages(workspaceRoot, baseHref, appShellOptions, prerende
|
|
|
54
54
|
// Get routes to prerender
|
|
55
55
|
const { errors: extractionErrors, serializedRouteTree: serializableRouteTreeNode, appShellRoute, } = await getAllRoutes(workspaceRoot, baseHref, outputFilesForWorker, assetsReversed, appShellOptions, prerenderOptions, sourcemap, outputMode).catch((err) => {
|
|
56
56
|
return {
|
|
57
|
-
errors: [`An error occurred while extracting routes.\n\n${err.
|
|
57
|
+
errors: [`An error occurred while extracting routes.\n\n${err.message ?? err.stack ?? err}`],
|
|
58
58
|
serializedRouteTree: [],
|
|
59
59
|
appShellRoute: undefined,
|
|
60
60
|
};
|
|
@@ -150,7 +150,7 @@ async function renderPages(baseHref, sourcemap, serializableRouteTreeNode, maxTh
|
|
|
150
150
|
}
|
|
151
151
|
})
|
|
152
152
|
.catch((err) => {
|
|
153
|
-
errors.push(`An error occurred while prerendering route '${route}'.\n\n${err.
|
|
153
|
+
errors.push(`An error occurred while prerendering route '${route}'.\n\n${err.message ?? err.stack ?? err.code ?? err}`);
|
|
154
154
|
void renderWorker.destroy();
|
|
155
155
|
});
|
|
156
156
|
renderingPromises.push(renderResult);
|
|
@@ -222,7 +222,7 @@ async function getAllRoutes(workspaceRoot, baseHref, outputFilesForWorker, asset
|
|
|
222
222
|
(0, error_1.assertIsError)(err);
|
|
223
223
|
return {
|
|
224
224
|
errors: [
|
|
225
|
-
`An error occurred while extracting routes.\n\n${err.
|
|
225
|
+
`An error occurred while extracting routes.\n\n${err.message ?? err.stack ?? err.code ?? err}`,
|
|
226
226
|
],
|
|
227
227
|
serializedRouteTree: [],
|
|
228
228
|
};
|