@angular-devkit/build-angular 15.0.0-next.4 → 15.0.0-next.5
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/app-shell/index.js +39 -40
- package/src/builders/app-shell/render-worker.d.ts +36 -0
- package/src/builders/app-shell/render-worker.js +82 -0
- package/src/builders/browser/index.d.ts +2 -0
- package/src/builders/browser/index.js +38 -19
- package/src/builders/browser/schema.json +2 -2
- package/src/builders/browser-esbuild/compiler-plugin.d.ts +1 -0
- package/src/builders/browser-esbuild/compiler-plugin.js +125 -53
- package/src/builders/browser-esbuild/index.js +3 -2
- package/src/builders/browser-esbuild/profiling.d.ts +11 -0
- package/src/builders/browser-esbuild/profiling.js +64 -0
- package/src/builders/browser-esbuild/sass-plugin.js +11 -5
- package/src/builders/browser-esbuild/schema.json +2 -2
- package/src/builders/dev-server/index.d.ts +2 -0
- package/src/builders/dev-server/index.js +10 -7
- package/src/builders/karma/find-tests-plugin.js +1 -0
- package/src/builders/server/schema.json +1 -1
- package/src/utils/environment-options.d.ts +1 -0
- package/src/utils/environment-options.js +3 -1
- package/src/webpack/configs/common.js +29 -5
- package/src/webpack/configs/index.d.ts +0 -1
- package/src/webpack/configs/index.js +0 -1
- package/src/webpack/configs/styles.js +21 -4
- package/src/webpack/plugins/occurrences-plugin.d.ts +18 -0
- package/src/webpack/plugins/occurrences-plugin.js +79 -0
- package/src/webpack/utils/stats.d.ts +13 -8
- package/src/webpack/utils/stats.js +57 -6
- package/src/webpack/configs/analytics.d.ts +0 -11
- package/src/webpack/configs/analytics.js +0 -27
- package/src/webpack/plugins/analytics.d.ts +0 -66
- package/src/webpack/plugins/analytics.js +0 -236
|
@@ -43,6 +43,7 @@ const typescript_1 = __importDefault(require("typescript"));
|
|
|
43
43
|
const application_1 = __importDefault(require("../../babel/presets/application"));
|
|
44
44
|
const webpack_loader_1 = require("../../babel/webpack-loader");
|
|
45
45
|
const load_esm_1 = require("../../utils/load-esm");
|
|
46
|
+
const profiling_1 = require("./profiling");
|
|
46
47
|
const stylesheets_1 = require("./stylesheets");
|
|
47
48
|
/**
|
|
48
49
|
* Converts TypeScript Diagnostic related information into an esbuild compatible note object.
|
|
@@ -113,10 +114,12 @@ class SourceFileCache extends Map {
|
|
|
113
114
|
constructor() {
|
|
114
115
|
super(...arguments);
|
|
115
116
|
this.modifiedFiles = new Set();
|
|
117
|
+
this.babelFileCache = new Map();
|
|
116
118
|
}
|
|
117
119
|
invalidate(files) {
|
|
118
120
|
this.modifiedFiles.clear();
|
|
119
121
|
for (let file of files) {
|
|
122
|
+
this.babelFileCache.delete(file);
|
|
120
123
|
// Normalize separators to allow matching TypeScript Host paths
|
|
121
124
|
if (USING_WINDOWS) {
|
|
122
125
|
file = file.replace(WINDOWS_SEP_REGEXP, path.posix.sep);
|
|
@@ -136,14 +139,15 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
|
|
|
136
139
|
async setup(build) {
|
|
137
140
|
var _a, _b;
|
|
138
141
|
var _c;
|
|
142
|
+
let setupWarnings;
|
|
139
143
|
// This uses a wrapped dynamic import to load `@angular/compiler-cli` which is ESM.
|
|
140
144
|
// Once TypeScript provides support for retaining dynamic imports this workaround can be dropped.
|
|
141
|
-
const
|
|
145
|
+
const { GLOBAL_DEFS_FOR_TERSER_WITH_AOT, NgtscProgram, OptimizeFor, readConfiguration } = await (0, load_esm_1.loadEsmModule)('@angular/compiler-cli');
|
|
142
146
|
// Temporary deep import for transformer support
|
|
143
147
|
const { mergeTransformers, replaceBootstrap, } = require('@ngtools/webpack/src/ivy/transformation');
|
|
144
148
|
// Setup defines based on the values provided by the Angular compiler-cli
|
|
145
149
|
(_a = (_c = build.initialOptions).define) !== null && _a !== void 0 ? _a : (_c.define = {});
|
|
146
|
-
for (const [key, value] of Object.entries(
|
|
150
|
+
for (const [key, value] of Object.entries(GLOBAL_DEFS_FOR_TERSER_WITH_AOT)) {
|
|
147
151
|
if (key in build.initialOptions.define) {
|
|
148
152
|
// Skip keys that have been manually provided
|
|
149
153
|
continue;
|
|
@@ -154,7 +158,7 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
|
|
|
154
158
|
}
|
|
155
159
|
// The tsconfig is loaded in setup instead of in start to allow the esbuild target build option to be modified.
|
|
156
160
|
// esbuild build options can only be modified in setup prior to starting the build.
|
|
157
|
-
const { options: compilerOptions, rootNames, errors: configurationDiagnostics, } =
|
|
161
|
+
const { options: compilerOptions, rootNames, errors: configurationDiagnostics, } = (0, profiling_1.profileSync)('NG_READ_CONFIG', () => readConfiguration(pluginOptions.tsconfig, {
|
|
158
162
|
noEmitOnError: false,
|
|
159
163
|
suppressOutputPathCheck: true,
|
|
160
164
|
outDir: undefined,
|
|
@@ -168,14 +172,24 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
|
|
|
168
172
|
allowEmptyCodegenFiles: false,
|
|
169
173
|
annotationsAs: 'decorators',
|
|
170
174
|
enableResourceInlining: false,
|
|
171
|
-
});
|
|
175
|
+
}));
|
|
172
176
|
if (compilerOptions.target === undefined || compilerOptions.target < typescript_1.default.ScriptTarget.ES2022) {
|
|
173
177
|
// If 'useDefineForClassFields' is already defined in the users project leave the value as is.
|
|
174
178
|
// Otherwise fallback to false due to https://github.com/microsoft/TypeScript/issues/45995
|
|
175
179
|
// which breaks the deprecated `@Effects` NGRX decorator and potentially other existing code as well.
|
|
176
180
|
compilerOptions.target = typescript_1.default.ScriptTarget.ES2022;
|
|
177
181
|
(_b = compilerOptions.useDefineForClassFields) !== null && _b !== void 0 ? _b : (compilerOptions.useDefineForClassFields = false);
|
|
178
|
-
|
|
182
|
+
(setupWarnings !== null && setupWarnings !== void 0 ? setupWarnings : (setupWarnings = [])).push({
|
|
183
|
+
text: 'TypeScript compiler options "target" and "useDefineForClassFields" are set to "ES2022" and ' +
|
|
184
|
+
'"false" respectively by the Angular CLI.',
|
|
185
|
+
location: { file: pluginOptions.tsconfig },
|
|
186
|
+
notes: [
|
|
187
|
+
{
|
|
188
|
+
text: `To control ECMA version and features use the Browerslist configuration. ' +
|
|
189
|
+
'For more information, see https://github.com/browserslist/browserslist#queries'`,
|
|
190
|
+
},
|
|
191
|
+
],
|
|
192
|
+
});
|
|
179
193
|
}
|
|
180
194
|
// The file emitter created during `onStart` that will be used during the build in `onLoad` callbacks for TS files
|
|
181
195
|
let fileEmitter;
|
|
@@ -183,10 +197,16 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
|
|
|
183
197
|
let stylesheetResourceFiles;
|
|
184
198
|
let previousBuilder;
|
|
185
199
|
let previousAngularProgram;
|
|
186
|
-
const
|
|
200
|
+
const babelDataCache = new Map();
|
|
201
|
+
const diagnosticCache = new WeakMap();
|
|
187
202
|
build.onStart(async () => {
|
|
188
|
-
|
|
189
|
-
|
|
203
|
+
const result = {
|
|
204
|
+
warnings: setupWarnings,
|
|
205
|
+
};
|
|
206
|
+
// Reset the setup warnings so that they are only shown during the first build.
|
|
207
|
+
setupWarnings = undefined;
|
|
208
|
+
// Reset debug performance tracking
|
|
209
|
+
(0, profiling_1.resetCumulativeDurations)();
|
|
190
210
|
// Reset stylesheet resource output files
|
|
191
211
|
stylesheetResourceFiles = [];
|
|
192
212
|
// Create TypeScript compiler host
|
|
@@ -241,15 +261,14 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
|
|
|
241
261
|
};
|
|
242
262
|
}
|
|
243
263
|
// Create the Angular specific program that contains the Angular compiler
|
|
244
|
-
const angularProgram = new
|
|
264
|
+
const angularProgram = (0, profiling_1.profileSync)('NG_CREATE_PROGRAM', () => new NgtscProgram(rootNames, compilerOptions, host, previousAngularProgram));
|
|
245
265
|
previousAngularProgram = angularProgram;
|
|
246
266
|
const angularCompiler = angularProgram.compiler;
|
|
247
|
-
const { ignoreForDiagnostics } = angularCompiler;
|
|
248
267
|
const typeScriptProgram = angularProgram.getTsProgram();
|
|
249
268
|
augmentProgramWithVersioning(typeScriptProgram);
|
|
250
269
|
const builder = typescript_1.default.createEmitAndSemanticDiagnosticsBuilderProgram(typeScriptProgram, host, previousBuilder, configurationDiagnostics);
|
|
251
270
|
previousBuilder = builder;
|
|
252
|
-
await angularCompiler.analyzeAsync();
|
|
271
|
+
await (0, profiling_1.profileAsync)('NG_ANALYZE_PROGRAM', () => angularCompiler.analyzeAsync());
|
|
253
272
|
function* collectDiagnostics() {
|
|
254
273
|
// Collect program level diagnostics
|
|
255
274
|
yield* builder.getConfigFileParsingDiagnostics();
|
|
@@ -257,32 +276,49 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
|
|
|
257
276
|
yield* builder.getOptionsDiagnostics();
|
|
258
277
|
yield* builder.getGlobalDiagnostics();
|
|
259
278
|
// Collect source file specific diagnostics
|
|
260
|
-
const
|
|
279
|
+
const affectedFiles = findAffectedFiles(builder, angularCompiler);
|
|
280
|
+
const optimizeFor = affectedFiles.size > 1 ? OptimizeFor.WholeProgram : OptimizeFor.SingleFile;
|
|
261
281
|
for (const sourceFile of builder.getSourceFiles()) {
|
|
262
|
-
if (ignoreForDiagnostics.has(sourceFile)) {
|
|
282
|
+
if (angularCompiler.ignoreForDiagnostics.has(sourceFile)) {
|
|
263
283
|
continue;
|
|
264
284
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
yield*
|
|
285
|
+
// TypeScript will use cached diagnostics for files that have not been
|
|
286
|
+
// changed or affected for this build when using incremental building.
|
|
287
|
+
yield* (0, profiling_1.profileSync)('NG_DIAGNOSTICS_SYNTACTIC', () => builder.getSyntacticDiagnostics(sourceFile), true);
|
|
288
|
+
yield* (0, profiling_1.profileSync)('NG_DIAGNOSTICS_SEMANTIC', () => builder.getSemanticDiagnostics(sourceFile), true);
|
|
289
|
+
// Only request Angular template diagnostics for affected files to avoid
|
|
290
|
+
// overhead of template diagnostics for unchanged files.
|
|
291
|
+
if (affectedFiles.has(sourceFile)) {
|
|
292
|
+
const angularDiagnostics = (0, profiling_1.profileSync)('NG_DIAGNOSTICS_TEMPLATE', () => angularCompiler.getDiagnosticsForFile(sourceFile, optimizeFor), true);
|
|
293
|
+
diagnosticCache.set(sourceFile, angularDiagnostics);
|
|
294
|
+
yield* angularDiagnostics;
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
const angularDiagnostics = diagnosticCache.get(sourceFile);
|
|
298
|
+
if (angularDiagnostics) {
|
|
299
|
+
yield* angularDiagnostics;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
269
302
|
}
|
|
270
303
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
304
|
+
(0, profiling_1.profileSync)('NG_DIAGNOSTICS_TOTAL', () => {
|
|
305
|
+
var _a, _b;
|
|
306
|
+
for (const diagnostic of collectDiagnostics()) {
|
|
307
|
+
const message = convertTypeScriptDiagnostic(diagnostic, host);
|
|
308
|
+
if (diagnostic.category === typescript_1.default.DiagnosticCategory.Error) {
|
|
309
|
+
((_a = result.errors) !== null && _a !== void 0 ? _a : (result.errors = [])).push(message);
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
((_b = result.warnings) !== null && _b !== void 0 ? _b : (result.warnings = [])).push(message);
|
|
313
|
+
}
|
|
278
314
|
}
|
|
279
|
-
}
|
|
315
|
+
});
|
|
280
316
|
fileEmitter = createFileEmitter(builder, mergeTransformers(angularCompiler.prepareEmit().transformers, {
|
|
281
317
|
before: [replaceBootstrap(() => builder.getProgram().getTypeChecker())],
|
|
282
|
-
}), (sourceFile) => angularCompiler.
|
|
318
|
+
}), (sourceFile) => angularCompiler.incrementalCompilation.recordSuccessfulEmit(sourceFile));
|
|
283
319
|
return result;
|
|
284
320
|
});
|
|
285
|
-
build.onLoad({ filter: compilerOptions.allowJs ? /\.[cm]?[jt]sx?$/ : /\.[cm]?tsx?$/ }, async (
|
|
321
|
+
build.onLoad({ filter: compilerOptions.allowJs ? /\.[cm]?[jt]sx?$/ : /\.[cm]?tsx?$/ }, (args) => (0, profiling_1.profileAsync)('NG_EMIT_TS*', async () => {
|
|
286
322
|
var _a, _b, _c;
|
|
287
323
|
assert.ok(fileEmitter, 'Invalid plugin execution order');
|
|
288
324
|
const typescriptResult = await fileEmitter((_b = (_a = pluginOptions.fileReplacements) === null || _a === void 0 ? void 0 : _a[args.path]) !== null && _b !== void 0 ? _b : args.path);
|
|
@@ -306,23 +342,44 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
|
|
|
306
342
|
],
|
|
307
343
|
};
|
|
308
344
|
}
|
|
345
|
+
const data = (_c = typescriptResult.content) !== null && _c !== void 0 ? _c : '';
|
|
346
|
+
// The pre-transformed data is used as a cache key. Since the cache is memory only,
|
|
347
|
+
// the options cannot change and do not need to be represented in the key. If the
|
|
348
|
+
// cache is later stored to disk, then the options that affect transform output
|
|
349
|
+
// would need to be added to the key as well.
|
|
350
|
+
let contents = babelDataCache.get(data);
|
|
351
|
+
if (contents === undefined) {
|
|
352
|
+
contents = await transformWithBabel(args.path, data, pluginOptions);
|
|
353
|
+
babelDataCache.set(data, contents);
|
|
354
|
+
}
|
|
309
355
|
return {
|
|
310
|
-
contents
|
|
356
|
+
contents,
|
|
311
357
|
loader: 'js',
|
|
312
358
|
};
|
|
313
|
-
});
|
|
314
|
-
build.onLoad({ filter: /\.[cm]?js$/ }, async (
|
|
315
|
-
|
|
359
|
+
}, true));
|
|
360
|
+
build.onLoad({ filter: /\.[cm]?js$/ }, (args) => (0, profiling_1.profileAsync)('NG_EMIT_JS*', async () => {
|
|
361
|
+
var _a, _b;
|
|
362
|
+
// The filename is currently used as a cache key. Since the cache is memory only,
|
|
363
|
+
// the options cannot change and do not need to be represented in the key. If the
|
|
364
|
+
// cache is later stored to disk, then the options that affect transform output
|
|
365
|
+
// would need to be added to the key as well as a check for any change of content.
|
|
366
|
+
let contents = (_a = pluginOptions.sourceFileCache) === null || _a === void 0 ? void 0 : _a.babelFileCache.get(args.path);
|
|
367
|
+
if (contents === undefined) {
|
|
368
|
+
const data = await fs_1.promises.readFile(args.path, 'utf-8');
|
|
369
|
+
contents = await transformWithBabel(args.path, data, pluginOptions);
|
|
370
|
+
(_b = pluginOptions.sourceFileCache) === null || _b === void 0 ? void 0 : _b.babelFileCache.set(args.path, contents);
|
|
371
|
+
}
|
|
316
372
|
return {
|
|
317
|
-
contents
|
|
373
|
+
contents,
|
|
318
374
|
loader: 'js',
|
|
319
375
|
};
|
|
320
|
-
});
|
|
376
|
+
}, true));
|
|
321
377
|
build.onEnd((result) => {
|
|
322
378
|
var _a;
|
|
323
379
|
if (stylesheetResourceFiles.length) {
|
|
324
380
|
(_a = result.outputFiles) === null || _a === void 0 ? void 0 : _a.push(...stylesheetResourceFiles);
|
|
325
381
|
}
|
|
382
|
+
(0, profiling_1.logCumulativeDurations)();
|
|
326
383
|
});
|
|
327
384
|
},
|
|
328
385
|
};
|
|
@@ -388,25 +445,40 @@ async function transformWithBabel(filename, data, pluginOptions) {
|
|
|
388
445
|
});
|
|
389
446
|
return (_a = result === null || result === void 0 ? void 0 : result.code) !== null && _a !== void 0 ? _a : data;
|
|
390
447
|
}
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
448
|
+
function findAffectedFiles(builder, { ignoreForDiagnostics, ignoreForEmit, incrementalCompilation }) {
|
|
449
|
+
const affectedFiles = new Set();
|
|
450
|
+
// eslint-disable-next-line no-constant-condition
|
|
451
|
+
while (true) {
|
|
452
|
+
const result = builder.getSemanticDiagnosticsOfNextAffectedFile(undefined, (sourceFile) => {
|
|
453
|
+
// If the affected file is a TTC shim, add the shim's original source file.
|
|
454
|
+
// This ensures that changes that affect TTC are typechecked even when the changes
|
|
455
|
+
// are otherwise unrelated from a TS perspective and do not result in Ivy codegen changes.
|
|
456
|
+
// For example, changing @Input property types of a directive used in another component's
|
|
457
|
+
// template.
|
|
458
|
+
// A TTC shim is a file that has been ignored for diagnostics and has a filename ending in `.ngtypecheck.ts`.
|
|
459
|
+
if (ignoreForDiagnostics.has(sourceFile) && sourceFile.fileName.endsWith('.ngtypecheck.ts')) {
|
|
460
|
+
// This file name conversion relies on internal compiler logic and should be converted
|
|
461
|
+
// to an official method when available. 15 is length of `.ngtypecheck.ts`
|
|
462
|
+
const originalFilename = sourceFile.fileName.slice(0, -15) + '.ts';
|
|
463
|
+
const originalSourceFile = builder.getSourceFile(originalFilename);
|
|
464
|
+
if (originalSourceFile) {
|
|
465
|
+
affectedFiles.add(originalSourceFile);
|
|
466
|
+
}
|
|
467
|
+
return true;
|
|
468
|
+
}
|
|
469
|
+
return false;
|
|
470
|
+
});
|
|
471
|
+
if (!result) {
|
|
472
|
+
break;
|
|
473
|
+
}
|
|
474
|
+
affectedFiles.add(result.affected);
|
|
410
475
|
}
|
|
411
|
-
|
|
476
|
+
// A file is also affected if the Angular compiler requires it to be emitted
|
|
477
|
+
for (const sourceFile of builder.getSourceFiles()) {
|
|
478
|
+
if (ignoreForEmit.has(sourceFile) || incrementalCompilation.safeToSkipEmit(sourceFile)) {
|
|
479
|
+
continue;
|
|
480
|
+
}
|
|
481
|
+
affectedFiles.add(sourceFile);
|
|
482
|
+
}
|
|
483
|
+
return affectedFiles;
|
|
412
484
|
}
|
|
@@ -78,7 +78,7 @@ class ExecutionResult {
|
|
|
78
78
|
}
|
|
79
79
|
async function execute(options, context, rebuildState) {
|
|
80
80
|
var _a, _b, _c, _d;
|
|
81
|
-
const startTime =
|
|
81
|
+
const startTime = process.hrtime.bigint();
|
|
82
82
|
const { projectRoot, workspaceRoot, optimizationOptions, outputPath, assets, serviceWorkerOptions, indexHtmlOptions, } = options;
|
|
83
83
|
const target = (0, esbuild_targets_1.transformSupportedBrowsersToTargets)((0, supported_browsers_1.getSupportedBrowsers)(projectRoot, context.logger));
|
|
84
84
|
const codeBundleCache = options.watch
|
|
@@ -177,7 +177,8 @@ async function execute(options, context, rebuildState) {
|
|
|
177
177
|
return new ExecutionResult(false, codeResults.rebuild, codeBundleCache);
|
|
178
178
|
}
|
|
179
179
|
}
|
|
180
|
-
|
|
180
|
+
const buildTime = Number(process.hrtime.bigint() - startTime) / 10 ** 9;
|
|
181
|
+
context.logger.info(`Complete. [${buildTime.toFixed(3)} seconds]`);
|
|
181
182
|
return new ExecutionResult(true, codeResults.rebuild, codeBundleCache);
|
|
182
183
|
}
|
|
183
184
|
function createOutputFileFromText(path, text) {
|
|
@@ -0,0 +1,11 @@
|
|
|
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
|
+
export declare function resetCumulativeDurations(): void;
|
|
9
|
+
export declare function logCumulativeDurations(): void;
|
|
10
|
+
export declare function profileAsync<T>(name: string, action: () => Promise<T>, cumulative?: boolean): Promise<T>;
|
|
11
|
+
export declare function profileSync<T>(name: string, action: () => T, cumulative?: boolean): T;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Copyright Google LLC All Rights Reserved.
|
|
5
|
+
*
|
|
6
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
7
|
+
* found in the LICENSE file at https://angular.io/license
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.profileSync = exports.profileAsync = exports.logCumulativeDurations = exports.resetCumulativeDurations = void 0;
|
|
11
|
+
const environment_options_1 = require("../../utils/environment-options");
|
|
12
|
+
let cumulativeDurations;
|
|
13
|
+
function resetCumulativeDurations() {
|
|
14
|
+
cumulativeDurations === null || cumulativeDurations === void 0 ? void 0 : cumulativeDurations.clear();
|
|
15
|
+
}
|
|
16
|
+
exports.resetCumulativeDurations = resetCumulativeDurations;
|
|
17
|
+
function logCumulativeDurations() {
|
|
18
|
+
if (!environment_options_1.debugPerformance || !cumulativeDurations) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
for (const [name, duration] of cumulativeDurations) {
|
|
22
|
+
// eslint-disable-next-line no-console
|
|
23
|
+
console.log(`DURATION[${name}]: ${duration.toFixed(9)} seconds`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.logCumulativeDurations = logCumulativeDurations;
|
|
27
|
+
function recordDuration(name, startTime, cumulative) {
|
|
28
|
+
var _a;
|
|
29
|
+
const duration = Number(process.hrtime.bigint() - startTime) / 10 ** 9;
|
|
30
|
+
if (cumulative) {
|
|
31
|
+
cumulativeDurations !== null && cumulativeDurations !== void 0 ? cumulativeDurations : (cumulativeDurations = new Map());
|
|
32
|
+
cumulativeDurations.set(name, ((_a = cumulativeDurations.get(name)) !== null && _a !== void 0 ? _a : 0) + duration);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
// eslint-disable-next-line no-console
|
|
36
|
+
console.log(`DURATION[${name}]: ${duration.toFixed(9)} seconds`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async function profileAsync(name, action, cumulative) {
|
|
40
|
+
if (!environment_options_1.debugPerformance) {
|
|
41
|
+
return action();
|
|
42
|
+
}
|
|
43
|
+
const startTime = process.hrtime.bigint();
|
|
44
|
+
try {
|
|
45
|
+
return await action();
|
|
46
|
+
}
|
|
47
|
+
finally {
|
|
48
|
+
recordDuration(name, startTime, cumulative);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.profileAsync = profileAsync;
|
|
52
|
+
function profileSync(name, action, cumulative) {
|
|
53
|
+
if (!environment_options_1.debugPerformance) {
|
|
54
|
+
return action();
|
|
55
|
+
}
|
|
56
|
+
const startTime = process.hrtime.bigint();
|
|
57
|
+
try {
|
|
58
|
+
return action();
|
|
59
|
+
}
|
|
60
|
+
finally {
|
|
61
|
+
recordDuration(name, startTime, cumulative);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
exports.profileSync = profileSync;
|
|
@@ -31,7 +31,8 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
31
31
|
};
|
|
32
32
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
33
33
|
exports.createSassPlugin = void 0;
|
|
34
|
-
const
|
|
34
|
+
const node_path_1 = require("node:path");
|
|
35
|
+
const node_url_1 = require("node:url");
|
|
35
36
|
function createSassPlugin(options) {
|
|
36
37
|
return {
|
|
37
38
|
name: 'angular-sass',
|
|
@@ -59,14 +60,16 @@ function createSassPlugin(options) {
|
|
|
59
60
|
});
|
|
60
61
|
return {
|
|
61
62
|
loader: 'css',
|
|
62
|
-
contents: sourceMap
|
|
63
|
-
|
|
63
|
+
contents: sourceMap
|
|
64
|
+
? `${css}\n${sourceMapToUrlComment(sourceMap, (0, node_path_1.dirname)(args.path))}`
|
|
65
|
+
: css,
|
|
66
|
+
watchFiles: loadedUrls.map((url) => (0, node_url_1.fileURLToPath)(url)),
|
|
64
67
|
warnings,
|
|
65
68
|
};
|
|
66
69
|
}
|
|
67
70
|
catch (error) {
|
|
68
71
|
if (error instanceof sass.Exception) {
|
|
69
|
-
const file = error.span.url ? (0,
|
|
72
|
+
const file = error.span.url ? (0, node_url_1.fileURLToPath)(error.span.url) : undefined;
|
|
70
73
|
return {
|
|
71
74
|
loader: 'css',
|
|
72
75
|
errors: [
|
|
@@ -84,7 +87,10 @@ function createSassPlugin(options) {
|
|
|
84
87
|
};
|
|
85
88
|
}
|
|
86
89
|
exports.createSassPlugin = createSassPlugin;
|
|
87
|
-
function sourceMapToUrlComment(sourceMap) {
|
|
90
|
+
function sourceMapToUrlComment(sourceMap, root) {
|
|
91
|
+
// Remove `file` protocol from all sourcemap sources and adjust to be relative to the input file.
|
|
92
|
+
// This allows esbuild to correctly process the paths.
|
|
93
|
+
sourceMap.sources = sourceMap.sources.map((source) => (0, node_path_1.relative)(root, (0, node_url_1.fileURLToPath)(source)));
|
|
88
94
|
const urlSourceMap = Buffer.from(JSON.stringify(sourceMap), 'utf-8').toString('base64');
|
|
89
95
|
return `/*# sourceMappingURL=data:application/json;charset=utf-8;base64,${urlSourceMap} */`;
|
|
90
96
|
}
|
|
@@ -141,8 +141,8 @@
|
|
|
141
141
|
},
|
|
142
142
|
"optimization": {
|
|
143
143
|
"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.",
|
|
144
|
-
"x-user-analytics": 16,
|
|
145
144
|
"default": true,
|
|
145
|
+
"x-user-analytics": "ep.ng_optimization",
|
|
146
146
|
"oneOf": [
|
|
147
147
|
{
|
|
148
148
|
"type": "object",
|
|
@@ -224,7 +224,7 @@
|
|
|
224
224
|
"aot": {
|
|
225
225
|
"type": "boolean",
|
|
226
226
|
"description": "Build using Ahead of Time compilation.",
|
|
227
|
-
"x-user-analytics":
|
|
227
|
+
"x-user-analytics": "ep.ng_aot",
|
|
228
228
|
"default": true
|
|
229
229
|
},
|
|
230
230
|
"sourceMap": {
|
|
@@ -12,6 +12,7 @@ import { Observable } from 'rxjs';
|
|
|
12
12
|
import webpack from 'webpack';
|
|
13
13
|
import { ExecutionTransformer } from '../../transforms';
|
|
14
14
|
import { IndexHtmlTransform } from '../../utils/index-file/index-html-generator';
|
|
15
|
+
import { BuildEventStats } from '../../webpack/utils/stats';
|
|
15
16
|
import { Schema } from './schema';
|
|
16
17
|
export declare type DevServerBuilderOptions = Schema;
|
|
17
18
|
/**
|
|
@@ -19,6 +20,7 @@ export declare type DevServerBuilderOptions = Schema;
|
|
|
19
20
|
*/
|
|
20
21
|
export declare type DevServerBuilderOutput = DevServerBuildOutput & {
|
|
21
22
|
baseUrl: string;
|
|
23
|
+
stats: BuildEventStats;
|
|
22
24
|
};
|
|
23
25
|
/**
|
|
24
26
|
* Reusable implementation of the Angular Webpack development server builder.
|
|
@@ -132,12 +132,7 @@ function serveWebpackBrowser(options, context, transforms = {}) {
|
|
|
132
132
|
****************************************************************************************
|
|
133
133
|
`);
|
|
134
134
|
}
|
|
135
|
-
const { config, projectRoot, i18n } = await (0, webpack_browser_config_1.generateI18nBrowserWebpackConfigFromContext)(browserOptions, context, (wco) => [
|
|
136
|
-
(0, configs_1.getDevServerConfig)(wco),
|
|
137
|
-
(0, configs_1.getCommonConfig)(wco),
|
|
138
|
-
(0, configs_1.getStylesConfig)(wco),
|
|
139
|
-
(0, configs_1.getAnalyticsConfig)(wco, context),
|
|
140
|
-
], options);
|
|
135
|
+
const { config, projectRoot, i18n } = await (0, webpack_browser_config_1.generateI18nBrowserWebpackConfigFromContext)(browserOptions, context, (wco) => [(0, configs_1.getDevServerConfig)(wco), (0, configs_1.getCommonConfig)(wco), (0, configs_1.getStylesConfig)(wco)], options);
|
|
141
136
|
if (!config.devServer) {
|
|
142
137
|
throw new Error('Webpack Dev Server configuration was not set.');
|
|
143
138
|
}
|
|
@@ -207,6 +202,10 @@ function serveWebpackBrowser(options, context, transforms = {}) {
|
|
|
207
202
|
webpackDevServerFactory: require('webpack-dev-server'),
|
|
208
203
|
}).pipe((0, operators_1.concatMap)(async (buildEvent, index) => {
|
|
209
204
|
var _a, _b;
|
|
205
|
+
const webpackRawStats = buildEvent.webpackStats;
|
|
206
|
+
if (!webpackRawStats) {
|
|
207
|
+
throw new Error('Webpack stats build result is required.');
|
|
208
|
+
}
|
|
210
209
|
// Resolve serve address.
|
|
211
210
|
const publicPath = (_b = (_a = webpackConfig.devServer) === null || _a === void 0 ? void 0 : _a.devMiddleware) === null || _b === void 0 ? void 0 : _b.publicPath;
|
|
212
211
|
const serverAddress = url.format({
|
|
@@ -235,7 +234,11 @@ function serveWebpackBrowser(options, context, transforms = {}) {
|
|
|
235
234
|
else {
|
|
236
235
|
logger.info(`\n${color_1.colors.redBright(color_1.colors.symbols.cross)} Failed to compile.`);
|
|
237
236
|
}
|
|
238
|
-
return {
|
|
237
|
+
return {
|
|
238
|
+
...buildEvent,
|
|
239
|
+
baseUrl: serverAddress,
|
|
240
|
+
stats: (0, stats_1.generateBuildEventStats)(webpackRawStats, browserOptions),
|
|
241
|
+
};
|
|
239
242
|
}));
|
|
240
243
|
}));
|
|
241
244
|
}
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
},
|
|
37
37
|
"optimization": {
|
|
38
38
|
"description": "Enables optimization of the build output. Including minification of scripts and styles, tree-shaking and dead-code elimination. For more information, see https://angular.io/guide/workspace-config#optimization-configuration.",
|
|
39
|
-
"x-user-analytics": 16,
|
|
40
39
|
"default": true,
|
|
40
|
+
"x-user-analytics": "ep.ng_optimization",
|
|
41
41
|
"oneOf": [
|
|
42
42
|
{
|
|
43
43
|
"type": "object",
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* found in the LICENSE file at https://angular.io/license
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.useLegacySass = exports.maxWorkers = exports.allowMinify = exports.shouldBeautify = exports.allowMangle = void 0;
|
|
10
|
+
exports.debugPerformance = exports.useLegacySass = exports.maxWorkers = exports.allowMinify = exports.shouldBeautify = exports.allowMangle = void 0;
|
|
11
11
|
const color_1 = require("./color");
|
|
12
12
|
function isDisabled(variable) {
|
|
13
13
|
return variable === '0' || variable.toLowerCase() === 'false';
|
|
@@ -77,3 +77,5 @@ exports.useLegacySass = (() => {
|
|
|
77
77
|
console.warn(color_1.colors.yellow(`Warning: 'NG_BUILD_LEGACY_SASS' environment variable support will be removed in version 16.`));
|
|
78
78
|
return isEnabled(legacySassVariable);
|
|
79
79
|
})();
|
|
80
|
+
const debugPerfVariable = process.env['NG_BUILD_DEBUG_PERF'];
|
|
81
|
+
exports.debugPerformance = isPresent(debugPerfVariable) && isEnabled(debugPerfVariable);
|
|
@@ -44,6 +44,7 @@ const load_esm_1 = require("../../utils/load-esm");
|
|
|
44
44
|
const plugins_1 = require("../plugins");
|
|
45
45
|
const devtools_ignore_plugin_1 = require("../plugins/devtools-ignore-plugin");
|
|
46
46
|
const named_chunks_plugin_1 = require("../plugins/named-chunks-plugin");
|
|
47
|
+
const occurrences_plugin_1 = require("../plugins/occurrences-plugin");
|
|
47
48
|
const progress_plugin_1 = require("../plugins/progress-plugin");
|
|
48
49
|
const transfer_size_plugin_1 = require("../plugins/transfer-size-plugin");
|
|
49
50
|
const typescript_1 = require("../plugins/typescript");
|
|
@@ -52,7 +53,7 @@ const helpers_1 = require("../utils/helpers");
|
|
|
52
53
|
const VENDORS_TEST = /[\\/]node_modules[\\/]/;
|
|
53
54
|
// eslint-disable-next-line max-lines-per-function
|
|
54
55
|
async function getCommonConfig(wco) {
|
|
55
|
-
var _a, _b;
|
|
56
|
+
var _a, _b, _c;
|
|
56
57
|
const { root, projectRoot, buildOptions, tsConfig, projectName, sourceRoot, tsConfigPath } = wco;
|
|
57
58
|
const { cache, codeCoverage, crossOrigin = 'none', platform = 'browser', aot = true, codeCoverageExclude = [], main, polyfills, sourceMap: { styles: stylesSourceMap, scripts: scriptsSourceMap, vendor: vendorSourceMap, hidden: hiddenSourceMap, }, optimization: { styles: stylesOptimization, scripts: scriptsOptimization }, commonChunk, vendorChunk, subresourceIntegrity, verbose, poll, webWorkerTsConfig, externalDependencies = [], allowedCommonJsDependencies, } = buildOptions;
|
|
58
59
|
const isPlatformServer = buildOptions.platform === 'server';
|
|
@@ -68,13 +69,28 @@ async function getCommonConfig(wco) {
|
|
|
68
69
|
if (buildOptions.progress) {
|
|
69
70
|
extraPlugins.push(new progress_plugin_1.ProgressPlugin(platform));
|
|
70
71
|
}
|
|
72
|
+
const localizePackageInitEntryPoint = '@angular/localize/init';
|
|
73
|
+
const hasLocalizeType = (_a = tsConfig.options.types) === null || _a === void 0 ? void 0 : _a.some((t) => t === '@angular/localize' || t === localizePackageInitEntryPoint);
|
|
74
|
+
if (hasLocalizeType) {
|
|
75
|
+
entryPoints['main'] = [localizePackageInitEntryPoint];
|
|
76
|
+
}
|
|
71
77
|
if (buildOptions.main) {
|
|
72
78
|
const mainPath = path.resolve(root, buildOptions.main);
|
|
73
|
-
entryPoints['main']
|
|
79
|
+
if (Array.isArray(entryPoints['main'])) {
|
|
80
|
+
entryPoints['main'].push(mainPath);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
entryPoints['main'] = [mainPath];
|
|
84
|
+
}
|
|
74
85
|
}
|
|
75
86
|
if (isPlatformServer) {
|
|
76
87
|
// Fixes Critical dependency: the request of a dependency is an expression
|
|
77
88
|
extraPlugins.push(new webpack_2.ContextReplacementPlugin(/@?hapi|express[\\/]/));
|
|
89
|
+
if (Array.isArray(entryPoints['main'])) {
|
|
90
|
+
// This import must come before any imports (direct or transitive) that rely on DOM built-ins being
|
|
91
|
+
// available, such as `@angular/elements`.
|
|
92
|
+
entryPoints['main'].unshift('@angular/platform-server/init');
|
|
93
|
+
}
|
|
78
94
|
}
|
|
79
95
|
if (polyfills === null || polyfills === void 0 ? void 0 : polyfills.length) {
|
|
80
96
|
// `zone.js/testing` is a **special** polyfill because when not imported in the main it fails with the below errors:
|
|
@@ -253,9 +269,9 @@ async function getCommonConfig(wco) {
|
|
|
253
269
|
output: {
|
|
254
270
|
uniqueName: projectName,
|
|
255
271
|
hashFunction: 'xxhash64',
|
|
256
|
-
clean: (
|
|
272
|
+
clean: (_b = buildOptions.deleteOutputPath) !== null && _b !== void 0 ? _b : true,
|
|
257
273
|
path: path.resolve(root, buildOptions.outputPath),
|
|
258
|
-
publicPath: (
|
|
274
|
+
publicPath: (_c = buildOptions.deployUrl) !== null && _c !== void 0 ? _c : '',
|
|
259
275
|
filename: `[name]${hashFormat.chunk}.js`,
|
|
260
276
|
chunkFilename: `[name]${hashFormat.chunk}.js`,
|
|
261
277
|
libraryTarget: isPlatformServer ? 'commonjs' : undefined,
|
|
@@ -385,7 +401,15 @@ async function getCommonConfig(wco) {
|
|
|
385
401
|
},
|
|
386
402
|
},
|
|
387
403
|
},
|
|
388
|
-
plugins: [
|
|
404
|
+
plugins: [
|
|
405
|
+
new named_chunks_plugin_1.NamedChunksPlugin(),
|
|
406
|
+
new occurrences_plugin_1.OccurrencesPlugin({
|
|
407
|
+
aot,
|
|
408
|
+
scriptsOptimization,
|
|
409
|
+
}),
|
|
410
|
+
new plugins_1.DedupeModuleResolvePlugin({ verbose }),
|
|
411
|
+
...extraPlugins,
|
|
412
|
+
],
|
|
389
413
|
node: false,
|
|
390
414
|
};
|
|
391
415
|
}
|