@angular-devkit/build-angular 15.0.0-next.4 → 15.0.0-next.6
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 +20 -17
- 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 +127 -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/karma/index.d.ts +1 -1
- package/src/builders/karma/index.js +4 -5
- package/src/builders/server/schema.json +1 -1
- package/src/sass/sass-service.d.ts +12 -1
- package/src/sass/sass-service.js +19 -11
- 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 +49 -25
- 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,46 @@ 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
|
+
const transformedData = await transformWithBabel(args.path, data, pluginOptions);
|
|
353
|
+
contents = Buffer.from(transformedData, 'utf-8');
|
|
354
|
+
babelDataCache.set(data, contents);
|
|
355
|
+
}
|
|
309
356
|
return {
|
|
310
|
-
contents
|
|
357
|
+
contents,
|
|
311
358
|
loader: 'js',
|
|
312
359
|
};
|
|
313
|
-
});
|
|
314
|
-
build.onLoad({ filter: /\.[cm]?js$/ }, async (
|
|
315
|
-
|
|
360
|
+
}, true));
|
|
361
|
+
build.onLoad({ filter: /\.[cm]?js$/ }, (args) => (0, profiling_1.profileAsync)('NG_EMIT_JS*', async () => {
|
|
362
|
+
var _a, _b;
|
|
363
|
+
// The filename is currently used as a cache key. Since the cache is memory only,
|
|
364
|
+
// the options cannot change and do not need to be represented in the key. If the
|
|
365
|
+
// cache is later stored to disk, then the options that affect transform output
|
|
366
|
+
// would need to be added to the key as well as a check for any change of content.
|
|
367
|
+
let contents = (_a = pluginOptions.sourceFileCache) === null || _a === void 0 ? void 0 : _a.babelFileCache.get(args.path);
|
|
368
|
+
if (contents === undefined) {
|
|
369
|
+
const data = await fs_1.promises.readFile(args.path, 'utf-8');
|
|
370
|
+
const transformedData = await transformWithBabel(args.path, data, pluginOptions);
|
|
371
|
+
contents = Buffer.from(transformedData, 'utf-8');
|
|
372
|
+
(_b = pluginOptions.sourceFileCache) === null || _b === void 0 ? void 0 : _b.babelFileCache.set(args.path, contents);
|
|
373
|
+
}
|
|
316
374
|
return {
|
|
317
|
-
contents
|
|
375
|
+
contents,
|
|
318
376
|
loader: 'js',
|
|
319
377
|
};
|
|
320
|
-
});
|
|
378
|
+
}, true));
|
|
321
379
|
build.onEnd((result) => {
|
|
322
380
|
var _a;
|
|
323
381
|
if (stylesheetResourceFiles.length) {
|
|
324
382
|
(_a = result.outputFiles) === null || _a === void 0 ? void 0 : _a.push(...stylesheetResourceFiles);
|
|
325
383
|
}
|
|
384
|
+
(0, profiling_1.logCumulativeDurations)();
|
|
326
385
|
});
|
|
327
386
|
},
|
|
328
387
|
};
|
|
@@ -388,25 +447,40 @@ async function transformWithBabel(filename, data, pluginOptions) {
|
|
|
388
447
|
});
|
|
389
448
|
return (_a = result === null || result === void 0 ? void 0 : result.code) !== null && _a !== void 0 ? _a : data;
|
|
390
449
|
}
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
450
|
+
function findAffectedFiles(builder, { ignoreForDiagnostics, ignoreForEmit, incrementalCompilation }) {
|
|
451
|
+
const affectedFiles = new Set();
|
|
452
|
+
// eslint-disable-next-line no-constant-condition
|
|
453
|
+
while (true) {
|
|
454
|
+
const result = builder.getSemanticDiagnosticsOfNextAffectedFile(undefined, (sourceFile) => {
|
|
455
|
+
// If the affected file is a TTC shim, add the shim's original source file.
|
|
456
|
+
// This ensures that changes that affect TTC are typechecked even when the changes
|
|
457
|
+
// are otherwise unrelated from a TS perspective and do not result in Ivy codegen changes.
|
|
458
|
+
// For example, changing @Input property types of a directive used in another component's
|
|
459
|
+
// template.
|
|
460
|
+
// A TTC shim is a file that has been ignored for diagnostics and has a filename ending in `.ngtypecheck.ts`.
|
|
461
|
+
if (ignoreForDiagnostics.has(sourceFile) && sourceFile.fileName.endsWith('.ngtypecheck.ts')) {
|
|
462
|
+
// This file name conversion relies on internal compiler logic and should be converted
|
|
463
|
+
// to an official method when available. 15 is length of `.ngtypecheck.ts`
|
|
464
|
+
const originalFilename = sourceFile.fileName.slice(0, -15) + '.ts';
|
|
465
|
+
const originalSourceFile = builder.getSourceFile(originalFilename);
|
|
466
|
+
if (originalSourceFile) {
|
|
467
|
+
affectedFiles.add(originalSourceFile);
|
|
468
|
+
}
|
|
469
|
+
return true;
|
|
470
|
+
}
|
|
471
|
+
return false;
|
|
472
|
+
});
|
|
473
|
+
if (!result) {
|
|
474
|
+
break;
|
|
475
|
+
}
|
|
476
|
+
affectedFiles.add(result.affected);
|
|
410
477
|
}
|
|
411
|
-
|
|
478
|
+
// A file is also affected if the Angular compiler requires it to be emitted
|
|
479
|
+
for (const sourceFile of builder.getSourceFiles()) {
|
|
480
|
+
if (ignoreForEmit.has(sourceFile) || incrementalCompilation.safeToSkipEmit(sourceFile)) {
|
|
481
|
+
continue;
|
|
482
|
+
}
|
|
483
|
+
affectedFiles.add(sourceFile);
|
|
484
|
+
}
|
|
485
|
+
return affectedFiles;
|
|
412
486
|
}
|
|
@@ -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
|
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* found in the LICENSE file at https://angular.io/license
|
|
7
7
|
*/
|
|
8
8
|
import { BuilderContext, BuilderOutput } from '@angular-devkit/architect';
|
|
9
|
-
import { ConfigOptions } from 'karma';
|
|
9
|
+
import type { ConfigOptions } from 'karma';
|
|
10
10
|
import { Observable } from 'rxjs';
|
|
11
11
|
import { Configuration } from 'webpack';
|
|
12
12
|
import { ExecutionTransformer } from '../../transforms';
|
|
@@ -33,7 +33,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
33
33
|
exports.execute = void 0;
|
|
34
34
|
const architect_1 = require("@angular-devkit/architect");
|
|
35
35
|
const core_1 = require("@angular-devkit/core");
|
|
36
|
-
const karma_1 = require("karma");
|
|
37
36
|
const module_1 = require("module");
|
|
38
37
|
const path = __importStar(require("path"));
|
|
39
38
|
const rxjs_1 = require("rxjs");
|
|
@@ -91,7 +90,7 @@ function execute(options, context, transforms = {}) {
|
|
|
91
90
|
}
|
|
92
91
|
const karmaOptions = options.karmaConfig
|
|
93
92
|
? {}
|
|
94
|
-
: getBuiltInKarmaConfig(context.workspaceRoot, projectName);
|
|
93
|
+
: getBuiltInKarmaConfig(karma, context.workspaceRoot, projectName);
|
|
95
94
|
karmaOptions.singleRun = singleRun;
|
|
96
95
|
// Convert browsers from a string to an array
|
|
97
96
|
if (options.browsers) {
|
|
@@ -130,7 +129,7 @@ function execute(options, context, transforms = {}) {
|
|
|
130
129
|
webpackConfig,
|
|
131
130
|
logger: context.logger,
|
|
132
131
|
};
|
|
133
|
-
const parsedKarmaConfig = await
|
|
132
|
+
const parsedKarmaConfig = await karma.config.parseConfig(options.karmaConfig && path.resolve(context.workspaceRoot, options.karmaConfig), transforms.karmaOptions ? transforms.karmaOptions(karmaOptions) : karmaOptions, { promiseConfig: true, throwErrors: true });
|
|
134
133
|
return [karma, parsedKarmaConfig];
|
|
135
134
|
}), (0, operators_1.switchMap)(([karma, karmaConfig]) => new rxjs_1.Observable((subscriber) => {
|
|
136
135
|
var _a, _b, _c;
|
|
@@ -154,7 +153,7 @@ function execute(options, context, transforms = {}) {
|
|
|
154
153
|
})), (0, operators_1.defaultIfEmpty)({ success: false }));
|
|
155
154
|
}
|
|
156
155
|
exports.execute = execute;
|
|
157
|
-
function getBuiltInKarmaConfig(workspaceRoot, projectName) {
|
|
156
|
+
function getBuiltInKarmaConfig(karma, workspaceRoot, projectName) {
|
|
158
157
|
let coverageFolderName = projectName.charAt(0) === '@' ? projectName.slice(1) : projectName;
|
|
159
158
|
if (/[A-Z]/.test(coverageFolderName)) {
|
|
160
159
|
coverageFolderName = core_1.strings.dasherize(coverageFolderName);
|
|
@@ -184,7 +183,7 @@ function getBuiltInKarmaConfig(workspaceRoot, projectName) {
|
|
|
184
183
|
reporters: ['progress', 'kjhtml'],
|
|
185
184
|
port: 9876,
|
|
186
185
|
colors: true,
|
|
187
|
-
logLevel:
|
|
186
|
+
logLevel: karma.constants.LOG_INFO,
|
|
188
187
|
autoWatch: true,
|
|
189
188
|
browsers: ['Chrome'],
|
|
190
189
|
restartOnFileChange: true,
|
|
@@ -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",
|
|
@@ -5,7 +5,17 @@
|
|
|
5
5
|
* Use of this source code is governed by an MIT-style license that can be
|
|
6
6
|
* found in the LICENSE file at https://angular.io/license
|
|
7
7
|
*/
|
|
8
|
-
import { CompileResult, StringOptionsWithImporter, StringOptionsWithoutImporter } from 'sass';
|
|
8
|
+
import { CompileResult, FileImporter, StringOptionsWithImporter, StringOptionsWithoutImporter } from 'sass';
|
|
9
|
+
declare type FileImporterOptions = Parameters<FileImporter['findFileUrl']>[1];
|
|
10
|
+
export interface FileImporterWithRequestContextOptions extends FileImporterOptions {
|
|
11
|
+
/**
|
|
12
|
+
* This is a custom option and is required as SASS does not provide context from which the file is being resolved.
|
|
13
|
+
* This breaks Yarn PNP as transitive deps cannot be resolved from the workspace root.
|
|
14
|
+
*
|
|
15
|
+
* Workaround until https://github.com/sass/sass/issues/3247 is addressed.
|
|
16
|
+
*/
|
|
17
|
+
previousResolvedModules?: Set<string>;
|
|
18
|
+
}
|
|
9
19
|
/**
|
|
10
20
|
* A Sass renderer implementation that provides an interface that can be used by Webpack's
|
|
11
21
|
* `sass-loader`. The implementation uses a Worker thread to perform the Sass rendering
|
|
@@ -45,3 +55,4 @@ export declare class SassWorkerImplementation {
|
|
|
45
55
|
private createRequest;
|
|
46
56
|
private isImporter;
|
|
47
57
|
}
|
|
58
|
+
export {};
|