Skip to content

Commit 86a257a

Browse files
alan-agius4Keen Yee Liau
authored and
Keen Yee Liau
committed
feat(@ngtools/webpack): integrate ngcc async
With this change we call NGCC async version prior to every build which will process the entire node modules tree.
1 parent 996b9c8 commit 86a257a

File tree

2 files changed

+62
-12
lines changed

2 files changed

+62
-12
lines changed

packages/ngtools/webpack/src/angular_compiler_plugin.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,8 @@ export class AngularCompilerPlugin {
777777
this._basePath,
778778
this._compilerOptions,
779779
);
780+
781+
ngccProcessor.process();
780782
}
781783

782784
// Use an identity function as all our paths are absolute already.

packages/ngtools/webpack/src/ngcc_processor.ts

Lines changed: 60 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88

99
import { Logger, PathMappings, process as mainNgcc } from '@angular/compiler-cli/ngcc';
10+
import { spawnSync } from 'child_process';
1011
import { accessSync, constants, existsSync } from 'fs';
1112
import * as path from 'path';
1213
import * as ts from 'typescript';
@@ -49,6 +50,52 @@ export class NgccProcessor {
4950
}
5051
}
5152

53+
/** Process the entire node modules tree. */
54+
process() {
55+
const timeLabel = 'NgccProcessor.process';
56+
time(timeLabel);
57+
58+
const corePackage = this.tryResolvePackage('@angular/core', this._nodeModulesDirectory);
59+
60+
// If the package.json is read only we should skip calling NGCC.
61+
// With Bazel when running under sandbox the filesystem is read-only.
62+
if (corePackage && isReadOnlyFile(corePackage)) {
63+
timeEnd(timeLabel);
64+
65+
return;
66+
}
67+
68+
// We spawn instead of using the API because:
69+
// - NGCC Async uses clustering which is problematic when used via the API which means
70+
// that we cannot setup multiple cluster masters with different options.
71+
// - We will not be able to have concurrent builds otherwise Ex: App-Shell,
72+
// as NGCC will create a lock file for both builds and it will cause builds to fails.
73+
const { status, error } = spawnSync(
74+
process.execPath,
75+
[
76+
require.resolve('@angular/compiler-cli/ngcc/main-ngcc.js'),
77+
'--source', /** basePath */
78+
this._nodeModulesDirectory,
79+
'--properties', /** propertiesToConsider */
80+
...this.propertiesToConsider,
81+
'--first-only', /** compileAllFormats */
82+
'--create-ivy-entry-points', /** createNewEntryPointFormats */
83+
'--async',
84+
],
85+
{
86+
stdio: ['inherit', process.stderr, process.stderr],
87+
},
88+
);
89+
90+
if (status !== 0) {
91+
const errorMessage = error?.message || '';
92+
throw new Error(errorMessage + `NGCC failed${errorMessage ? ', see above' : ''}.`);
93+
}
94+
95+
timeEnd(timeLabel);
96+
}
97+
98+
/** Process a module and it's depedencies. */
5299
processModule(
53100
moduleName: string,
54101
resolvedModule: ts.ResolvedModule | ts.ResolvedTypeReferenceDirective,
@@ -61,18 +108,9 @@ export class NgccProcessor {
61108
}
62109

63110
const packageJsonPath = this.tryResolvePackage(moduleName, resolvedFileName);
64-
if (!packageJsonPath) {
65-
// add it to processed so the second time round we skip this.
66-
this._processedModules.add(resolvedFileName);
67-
68-
return;
69-
}
70-
71111
// If the package.json is read only we should skip calling NGCC.
72112
// With Bazel when running under sandbox the filesystem is read-only.
73-
try {
74-
accessSync(packageJsonPath, constants.W_OK);
75-
} catch {
113+
if (!packageJsonPath || isReadOnlyFile(packageJsonPath)) {
76114
// add it to processed so the second time round we skip this.
77115
this._processedModules.add(resolvedFileName);
78116

@@ -145,9 +183,9 @@ class NgccLogger implements Logger {
145183
constructor(
146184
private readonly compilationWarnings: (Error | string)[],
147185
private readonly compilationErrors: (Error | string)[],
148-
) {}
186+
) { }
149187

150-
debug(..._args: string[]) {}
188+
debug(..._args: string[]) { }
151189

152190
info(...args: string[]) {
153191
// Log to stderr because it's a progress-like info message.
@@ -162,3 +200,13 @@ class NgccLogger implements Logger {
162200
this.compilationErrors.push(new Error(args.join(' ')));
163201
}
164202
}
203+
204+
function isReadOnlyFile(fileName: string): boolean {
205+
try {
206+
accessSync(fileName, constants.W_OK);
207+
208+
return false;
209+
} catch {
210+
return true;
211+
}
212+
}

0 commit comments

Comments
 (0)