Skip to content

Commit 6cf4da3

Browse files
author
Angular Builds
committed
dcbdca8 feat(@angular-devkit/build-angular): karma+esbuild+watch
1 parent f1bb82d commit 6cf4da3

File tree

4 files changed

+71
-23
lines changed

4 files changed

+71
-23
lines changed

package.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
{
22
"name": "@angular-devkit/build-angular",
3-
"version": "19.0.0-next.8+sha-32dd2f2",
3+
"version": "19.0.0-next.8+sha-dcbdca8",
44
"description": "Angular Webpack Build Facade",
55
"main": "src/index.js",
66
"typings": "src/index.d.ts",
77
"builders": "builders.json",
88
"dependencies": {
99
"@ampproject/remapping": "2.3.0",
10-
"@angular-devkit/architect": "github:angular/angular-devkit-architect-builds#32dd2f2",
11-
"@angular-devkit/build-webpack": "github:angular/angular-devkit-build-webpack-builds#32dd2f2",
12-
"@angular-devkit/core": "github:angular/angular-devkit-core-builds#32dd2f2",
13-
"@angular/build": "github:angular/angular-build-builds#32dd2f2",
10+
"@angular-devkit/architect": "github:angular/angular-devkit-architect-builds#dcbdca8",
11+
"@angular-devkit/build-webpack": "github:angular/angular-devkit-build-webpack-builds#dcbdca8",
12+
"@angular-devkit/core": "github:angular/angular-devkit-core-builds#dcbdca8",
13+
"@angular/build": "github:angular/angular-build-builds#dcbdca8",
1414
"@babel/core": "7.25.2",
1515
"@babel/generator": "7.25.6",
1616
"@babel/helper-annotate-as-pure": "7.24.7",
@@ -21,7 +21,7 @@
2121
"@babel/preset-env": "7.25.4",
2222
"@babel/runtime": "7.25.6",
2323
"@discoveryjs/json-ext": "0.6.1",
24-
"@ngtools/webpack": "github:angular/ngtools-webpack-builds#32dd2f2",
24+
"@ngtools/webpack": "github:angular/ngtools-webpack-builds#dcbdca8",
2525
"@vitejs/plugin-basic-ssl": "1.1.0",
2626
"ansi-colors": "4.1.3",
2727
"autoprefixer": "10.4.20",
@@ -77,7 +77,7 @@
7777
"@angular/localize": "^19.0.0-next.0",
7878
"@angular/platform-server": "^19.0.0-next.0",
7979
"@angular/service-worker": "^19.0.0-next.0",
80-
"@angular/ssr": "github:angular/angular-ssr-builds#32dd2f2",
80+
"@angular/ssr": "github:angular/angular-ssr-builds#dcbdca8",
8181
"@web/test-runner": "^0.19.0",
8282
"browser-sync": "^3.0.2",
8383
"jest": "^29.5.0",
@@ -98,7 +98,7 @@
9898
"@angular/service-worker": {
9999
"optional": true
100100
},
101-
"@angular/ssr": "github:angular/angular-ssr-builds#32dd2f2",
101+
"@angular/ssr": "github:angular/angular-ssr-builds#dcbdca8",
102102
"@web/test-runner": {
103103
"optional": true
104104
},

src/builders/karma/application_builder.js

Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,56 @@ class ApplicationBuildError extends Error {
5050
this.name = 'ApplicationBuildError';
5151
}
5252
}
53+
function injectKarmaReporter(context, buildOptions, karmaConfig, subscriber) {
54+
const reporterName = 'angular-progress-notifier';
55+
class ProgressNotifierReporter {
56+
emitter;
57+
static $inject = ['emitter'];
58+
constructor(emitter) {
59+
this.emitter = emitter;
60+
this.startWatchingBuild();
61+
}
62+
startWatchingBuild() {
63+
void (async () => {
64+
for await (const buildOutput of (0, private_1.buildApplicationInternal)({
65+
...buildOptions,
66+
watch: true,
67+
}, context)) {
68+
if (buildOutput.kind === private_1.ResultKind.Failure) {
69+
subscriber.next({ success: false, message: 'Build failed' });
70+
}
71+
else if (buildOutput.kind === private_1.ResultKind.Incremental ||
72+
buildOutput.kind === private_1.ResultKind.Full) {
73+
await writeTestFiles(buildOutput.files, buildOptions.outputPath);
74+
this.emitter.refreshFiles();
75+
}
76+
}
77+
})();
78+
}
79+
onRunComplete = function (_browsers, results) {
80+
if (results.exitCode === 0) {
81+
subscriber.next({ success: true });
82+
}
83+
else {
84+
subscriber.next({ success: false });
85+
}
86+
};
87+
}
88+
karmaConfig.reporters ??= [];
89+
karmaConfig.reporters.push(reporterName);
90+
karmaConfig.plugins ??= [];
91+
karmaConfig.plugins.push({
92+
[`reporter:${reporterName}`]: [
93+
'factory',
94+
Object.assign((...args) => new ProgressNotifierReporter(...args), ProgressNotifierReporter),
95+
],
96+
});
97+
}
5398
function execute(options, context, karmaOptions, transforms = {}) {
54-
return (0, rxjs_1.from)(initializeApplication(options, context, karmaOptions, transforms)).pipe((0, rxjs_1.switchMap)(([karma, karmaConfig]) => new rxjs_1.Observable((subscriber) => {
99+
return (0, rxjs_1.from)(initializeApplication(options, context, karmaOptions, transforms)).pipe((0, rxjs_1.switchMap)(([karma, karmaConfig, buildOptions]) => new rxjs_1.Observable((subscriber) => {
100+
if (options.watch) {
101+
injectKarmaReporter(context, buildOptions, karmaConfig, subscriber);
102+
}
55103
// Complete the observable once the Karma server returns.
56104
const karmaServer = new karma.Server(karmaConfig, (exitCode) => {
57105
subscriber.next({ success: exitCode === 0 });
@@ -98,19 +146,17 @@ async function initializeApplication(options, context, karmaOptions, transforms
98146
if (transforms.webpackConfiguration) {
99147
context.logger.warn(`This build is using the application builder but transforms.webpackConfiguration was provided. The transform will be ignored.`);
100148
}
101-
const testDir = path.join(context.workspaceRoot, 'dist/test-out', (0, crypto_1.randomUUID)());
149+
const outputPath = path.join(context.workspaceRoot, 'dist/test-out', (0, crypto_1.randomUUID)());
102150
const projectSourceRoot = await getProjectSourceRoot(context);
103151
const [karma, entryPoints] = await Promise.all([
104152
Promise.resolve().then(() => __importStar(require('karma'))),
105153
collectEntrypoints(options, context, projectSourceRoot),
106-
fs.rm(testDir, { recursive: true, force: true }),
154+
fs.rm(outputPath, { recursive: true, force: true }),
107155
]);
108-
const outputPath = testDir;
109156
const instrumentForCoverage = options.codeCoverage
110157
? createInstrumentationFilter(projectSourceRoot, getInstrumentationExcludedPaths(context.workspaceRoot, options.codeCoverageExclude ?? []))
111158
: undefined;
112-
// Build tests with `application` builder, using test files as entry points.
113-
const buildOutput = await first((0, private_1.buildApplicationInternal)({
159+
const buildOptions = {
114160
entryPoints,
115161
tsConfig: options.tsConfig,
116162
outputPath,
@@ -127,27 +173,29 @@ async function initializeApplication(options, context, karmaOptions, transforms
127173
styles: options.styles,
128174
polyfills: normalizePolyfills(options.polyfills),
129175
webWorkerTsConfig: options.webWorkerTsConfig,
130-
}, context));
176+
};
177+
// Build tests with `application` builder, using test files as entry points.
178+
const buildOutput = await first((0, private_1.buildApplicationInternal)(buildOptions, context));
131179
if (buildOutput.kind === private_1.ResultKind.Failure) {
132180
throw new ApplicationBuildError('Build failed');
133181
}
134182
else if (buildOutput.kind !== private_1.ResultKind.Full) {
135183
throw new ApplicationBuildError('A full build result is required from the application builder.');
136184
}
137185
// Write test files
138-
await writeTestFiles(buildOutput.files, testDir);
186+
await writeTestFiles(buildOutput.files, buildOptions.outputPath);
139187
karmaOptions.files ??= [];
140188
karmaOptions.files.push(
141189
// Serve polyfills first.
142-
{ pattern: `${testDir}/polyfills.js`, type: 'module' },
190+
{ pattern: `${outputPath}/polyfills.js`, type: 'module' },
143191
// Allow loading of chunk-* files but don't include them all on load.
144-
{ pattern: `${testDir}/{chunk,worker}-*.js`, type: 'module', included: false });
192+
{ pattern: `${outputPath}/{chunk,worker}-*.js`, type: 'module', included: false });
145193
karmaOptions.files.push(
146194
// Serve remaining JS on page load, these are the test entrypoints.
147-
{ pattern: `${testDir}/*.js`, type: 'module' });
195+
{ pattern: `${outputPath}/*.js`, type: 'module' });
148196
if (options.styles?.length) {
149197
// Serve CSS outputs on page load, these are the global styles.
150-
karmaOptions.files.push({ pattern: `${testDir}/*.css`, type: 'css' });
198+
karmaOptions.files.push({ pattern: `${outputPath}/*.css`, type: 'css' });
151199
}
152200
const parsedKarmaConfig = await karma.config.parseConfig(options.karmaConfig && path.resolve(context.workspaceRoot, options.karmaConfig), transforms.karmaOptions ? transforms.karmaOptions(karmaOptions) : karmaOptions, { promiseConfig: true, throwErrors: true });
153201
// Remove the webpack plugin/framework:
@@ -171,7 +219,7 @@ async function initializeApplication(options, context, karmaOptions, transforms
171219
!parsedKarmaConfig.reporters?.some((r) => r === 'coverage' || r === 'coverage-istanbul')) {
172220
parsedKarmaConfig.reporters = (parsedKarmaConfig.reporters ?? []).concat(['coverage']);
173221
}
174-
return [karma, parsedKarmaConfig];
222+
return [karma, parsedKarmaConfig, buildOptions];
175223
}
176224
async function writeTestFiles(files, testDir) {
177225
const directoryExists = new Set();

src/utils/normalize-cache.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
1010
exports.normalizeCacheOptions = normalizeCacheOptions;
1111
const node_path_1 = require("node:path");
1212
/** Version placeholder is replaced during the build process with actual package version */
13-
const VERSION = '19.0.0-next.8+sha-32dd2f2';
13+
const VERSION = '19.0.0-next.8+sha-dcbdca8';
1414
function hasCacheMetadata(value) {
1515
return (!!value &&
1616
typeof value === 'object' &&

uniqueId

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Mon Sep 30 2024 13:04:55 GMT+0000 (Coordinated Universal Time)
1+
Mon Sep 30 2024 21:47:34 GMT+0000 (Coordinated Universal Time)

0 commit comments

Comments
 (0)