Skip to content

Commit 4517f1a

Browse files
alan-agius4clydin
authored andcommitted
fix(@ngtools/webpack): only use require.resolve as a fallback in NGCC processing
Use `enhanced-resolve` instead of `require.resolve` to ensure that we can use symlink path instead of real-path when resolving a linked module. Closes #19395 (cherry picked from commit eb313f7)
1 parent d7330c4 commit 4517f1a

File tree

2 files changed

+23
-18
lines changed

2 files changed

+23
-18
lines changed

packages/ngtools/webpack/src/angular_compiler_plugin.ts

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -785,21 +785,14 @@ export class AngularCompilerPlugin {
785785

786786
let ngccProcessor: NgccProcessor | undefined;
787787
if (this._compilerOptions.enableIvy) {
788-
const fileWatchPurger = (path: string) => {
789-
// tslint:disable-next-line: no-any
790-
if ((compilerWithFileSystems.inputFileSystem as any).purge) {
791-
// tslint:disable-next-line: no-any
792-
(compilerWithFileSystems.inputFileSystem as any).purge(path);
793-
}
794-
};
795-
796788
ngccProcessor = new NgccProcessor(
797789
this._mainFields,
798-
fileWatchPurger,
799790
this._warnings,
800791
this._errors,
801792
this._basePath,
802793
this._tsConfigPath,
794+
compilerWithFileSystems.inputFileSystem,
795+
compiler.options.resolve?.symlinks,
803796
);
804797

805798
ngccProcessor.process();

packages/ngtools/webpack/src/ngcc_processor.ts

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99
import { LogLevel, Logger, process as mainNgcc } from '@angular/compiler-cli/ngcc';
1010
import { spawnSync } from 'child_process';
1111
import { createHash } from 'crypto';
12+
import { Resolver, ResolverFactory } from 'enhanced-resolve';
1213
import { accessSync, constants, existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
1314
import * as path from 'path';
1415
import * as ts from 'typescript';
16+
import { InputFileSystem } from 'webpack';
1517
import { time, timeEnd } from './benchmark';
1618

1719
// We cannot create a plugin for this, because NGTSC requires addition type
@@ -28,17 +30,28 @@ export class NgccProcessor {
2830
private _processedModules = new Set<string>();
2931
private _logger: NgccLogger;
3032
private _nodeModulesDirectory: string;
33+
private _resolver: Resolver;
3134

3235
constructor(
3336
private readonly propertiesToConsider: string[],
34-
private readonly fileWatchPurger: (path: string) => void,
3537
private readonly compilationWarnings: (Error | string)[],
3638
private readonly compilationErrors: (Error | string)[],
3739
private readonly basePath: string,
3840
private readonly tsConfigPath: string,
41+
private readonly inputFileSystem: InputFileSystem,
42+
private readonly symlinks: boolean | undefined,
3943
) {
4044
this._logger = new NgccLogger(this.compilationWarnings, this.compilationErrors);
4145
this._nodeModulesDirectory = this.findNodeModulesDirectory(this.basePath);
46+
47+
this._resolver = ResolverFactory.createResolver({
48+
// NOTE: @types/webpack InputFileSystem is missing some methods
49+
// tslint:disable-next-line: no-any
50+
fileSystem: this.inputFileSystem as any,
51+
extensions: ['.json'],
52+
useSyncFileSystemCalls: true,
53+
symlinks,
54+
});
4255
}
4356

4457
/** Process the entire node modules tree. */
@@ -191,7 +204,10 @@ export class NgccProcessor {
191204

192205
// Purge this file from cache, since NGCC add new mainFields. Ex: module_ivy_ngcc
193206
// which are unknown in the cached file.
194-
this.fileWatchPurger(packageJsonPath);
207+
if (this.inputFileSystem.purge) {
208+
// tslint:disable-next-line: no-any
209+
(this.inputFileSystem.purge as any)(packageJsonPath);
210+
}
195211

196212
this._processedModules.add(resolvedFileName);
197213
}
@@ -205,14 +221,10 @@ export class NgccProcessor {
205221
*/
206222
private tryResolvePackage(moduleName: string, resolvedFileName: string): string | undefined {
207223
try {
208-
// This is based on the logic in the NGCC compiler
209-
// tslint:disable-next-line:max-line-length
210-
// See: https://github.com/angular/angular/blob/b93c1dffa17e4e6900b3ab1b9e554b6da92be0de/packages/compiler-cli/src/ngcc/src/packages/dependency_host.ts#L85-L121
211-
return require.resolve(`${moduleName}/package.json`, {
212-
paths: [resolvedFileName],
213-
});
224+
const resolvedPath = this._resolver.resolveSync({}, resolvedFileName, `${moduleName}/package.json`);
225+
226+
return resolvedPath || undefined;
214227
} catch {
215-
// if it fails this might be a deep import which doesn't have a package.json
216228
// Ex: @angular/compiler/src/i18n/i18n_ast/package.json
217229
// or local libraries which don't reside in node_modules
218230
const packageJsonPath = path.resolve(resolvedFileName, '../package.json');

0 commit comments

Comments
 (0)