mirror of
https://github.com/angular/angular-cli.git
synced 2025-05-16 10:33:43 +08:00
refactor(@ngtools/webpack): remove NGCC integration
This commit removes usage of NGCC which was used to convert old View Engine libraries to Ivy. BREAKING CHANGE: NGCC integration has been removed and as a result Angular View Engine libraries will no longer work.
This commit is contained in:
parent
d2ef386f46
commit
c8ac660d8b
@ -11,7 +11,6 @@ import type { CompilerHost } from '@angular/compiler-cli';
|
|||||||
import { createHash } from 'crypto';
|
import { createHash } from 'crypto';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
import { NgccProcessor } from '../ngcc_processor';
|
|
||||||
import { WebpackResourceLoader } from '../resource_loader';
|
import { WebpackResourceLoader } from '../resource_loader';
|
||||||
import { normalizePath } from './paths';
|
import { normalizePath } from './paths';
|
||||||
|
|
||||||
@ -191,67 +190,6 @@ export function augmentHostWithDependencyCollection(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function augmentHostWithNgcc(
|
|
||||||
host: ts.CompilerHost,
|
|
||||||
ngcc: NgccProcessor,
|
|
||||||
moduleResolutionCache?: ts.ModuleResolutionCache,
|
|
||||||
): void {
|
|
||||||
augmentResolveModuleNames(
|
|
||||||
host,
|
|
||||||
(resolvedModule, moduleName) => {
|
|
||||||
if (resolvedModule && ngcc) {
|
|
||||||
ngcc.processModule(moduleName, resolvedModule);
|
|
||||||
}
|
|
||||||
|
|
||||||
return resolvedModule;
|
|
||||||
},
|
|
||||||
moduleResolutionCache,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (host.resolveTypeReferenceDirectives) {
|
|
||||||
const baseResolveTypeReferenceDirectives = host.resolveTypeReferenceDirectives;
|
|
||||||
host.resolveTypeReferenceDirectives = function (
|
|
||||||
names: string[] | ts.FileReference[],
|
|
||||||
...parameters
|
|
||||||
) {
|
|
||||||
return names.map((name) => {
|
|
||||||
const fileName = typeof name === 'string' ? name : name.fileName;
|
|
||||||
const result = baseResolveTypeReferenceDirectives.call(host, [fileName], ...parameters);
|
|
||||||
|
|
||||||
if (result[0] && ngcc) {
|
|
||||||
ngcc.processModule(fileName, result[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result[0];
|
|
||||||
});
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
host.resolveTypeReferenceDirectives = function (
|
|
||||||
moduleNames: string[] | ts.FileReference[],
|
|
||||||
containingFile: string,
|
|
||||||
redirectedReference: ts.ResolvedProjectReference | undefined,
|
|
||||||
options: ts.CompilerOptions,
|
|
||||||
) {
|
|
||||||
return moduleNames.map((name) => {
|
|
||||||
const fileName = typeof name === 'string' ? name : name.fileName;
|
|
||||||
const result = ts.resolveTypeReferenceDirective(
|
|
||||||
fileName,
|
|
||||||
containingFile,
|
|
||||||
options,
|
|
||||||
host,
|
|
||||||
redirectedReference,
|
|
||||||
).resolvedTypeReferenceDirective;
|
|
||||||
|
|
||||||
if (result && ngcc) {
|
|
||||||
ngcc.processModule(fileName, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function augmentHostWithReplacements(
|
export function augmentHostWithReplacements(
|
||||||
host: ts.CompilerHost,
|
host: ts.CompilerHost,
|
||||||
replacements: Record<string, string>,
|
replacements: Record<string, string>,
|
||||||
|
@ -10,7 +10,6 @@ import type { CompilerHost, CompilerOptions, NgtscProgram } from '@angular/compi
|
|||||||
import { strict as assert } from 'assert';
|
import { strict as assert } from 'assert';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
import type { Compilation, Compiler, Module, NormalModule } from 'webpack';
|
import type { Compilation, Compiler, Module, NormalModule } from 'webpack';
|
||||||
import { NgccProcessor } from '../ngcc_processor';
|
|
||||||
import { TypeScriptPathsPlugin } from '../paths-plugin';
|
import { TypeScriptPathsPlugin } from '../paths-plugin';
|
||||||
import { WebpackResourceLoader } from '../resource_loader';
|
import { WebpackResourceLoader } from '../resource_loader';
|
||||||
import { SourceFileCache } from './cache';
|
import { SourceFileCache } from './cache';
|
||||||
@ -23,7 +22,6 @@ import {
|
|||||||
import {
|
import {
|
||||||
augmentHostWithCaching,
|
augmentHostWithCaching,
|
||||||
augmentHostWithDependencyCollection,
|
augmentHostWithDependencyCollection,
|
||||||
augmentHostWithNgcc,
|
|
||||||
augmentHostWithReplacements,
|
augmentHostWithReplacements,
|
||||||
augmentHostWithResources,
|
augmentHostWithResources,
|
||||||
augmentHostWithSubstitutions,
|
augmentHostWithSubstitutions,
|
||||||
@ -57,48 +55,11 @@ export interface AngularWebpackPluginOptions {
|
|||||||
* The Angular compilation state that is maintained across each Webpack compilation.
|
* The Angular compilation state that is maintained across each Webpack compilation.
|
||||||
*/
|
*/
|
||||||
interface AngularCompilationState {
|
interface AngularCompilationState {
|
||||||
ngccProcessor?: NgccProcessor;
|
|
||||||
resourceLoader?: WebpackResourceLoader;
|
resourceLoader?: WebpackResourceLoader;
|
||||||
previousUnused?: Set<string>;
|
previousUnused?: Set<string>;
|
||||||
pathsPlugin: TypeScriptPathsPlugin;
|
pathsPlugin: TypeScriptPathsPlugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
function initializeNgccProcessor(
|
|
||||||
compiler: Compiler,
|
|
||||||
tsconfig: string,
|
|
||||||
compilerNgccModule: typeof import('@angular/compiler-cli/ngcc') | undefined,
|
|
||||||
): { processor: NgccProcessor; errors: string[]; warnings: string[] } {
|
|
||||||
const { inputFileSystem, options: webpackOptions } = compiler;
|
|
||||||
const mainFields = webpackOptions.resolve?.mainFields?.flat() ?? [];
|
|
||||||
|
|
||||||
const errors: string[] = [];
|
|
||||||
const warnings: string[] = [];
|
|
||||||
const resolver = compiler.resolverFactory.get('normal', {
|
|
||||||
// Caching must be disabled because it causes the resolver to become async after a rebuild
|
|
||||||
cache: false,
|
|
||||||
extensions: ['.json'],
|
|
||||||
useSyncFileSystemCalls: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
// The compilerNgccModule field is guaranteed to be defined during a compilation
|
|
||||||
// due to the `beforeCompile` hook. Usage of this property accessor prior to the
|
|
||||||
// hook execution is an implementation error.
|
|
||||||
assert.ok(compilerNgccModule, `'@angular/compiler-cli/ngcc' used prior to Webpack compilation.`);
|
|
||||||
|
|
||||||
const processor = new NgccProcessor(
|
|
||||||
compilerNgccModule,
|
|
||||||
mainFields,
|
|
||||||
warnings,
|
|
||||||
errors,
|
|
||||||
compiler.context,
|
|
||||||
tsconfig,
|
|
||||||
inputFileSystem,
|
|
||||||
resolver,
|
|
||||||
);
|
|
||||||
|
|
||||||
return { processor, errors, warnings };
|
|
||||||
}
|
|
||||||
|
|
||||||
const PLUGIN_NAME = 'angular-compiler';
|
const PLUGIN_NAME = 'angular-compiler';
|
||||||
const compilationFileEmitters = new WeakMap<Compilation, FileEmitterCollection>();
|
const compilationFileEmitters = new WeakMap<Compilation, FileEmitterCollection>();
|
||||||
|
|
||||||
@ -110,7 +71,6 @@ interface FileEmitHistoryItem {
|
|||||||
export class AngularWebpackPlugin {
|
export class AngularWebpackPlugin {
|
||||||
private readonly pluginOptions: AngularWebpackPluginOptions;
|
private readonly pluginOptions: AngularWebpackPluginOptions;
|
||||||
private compilerCliModule?: typeof import('@angular/compiler-cli');
|
private compilerCliModule?: typeof import('@angular/compiler-cli');
|
||||||
private compilerNgccModule?: typeof import('@angular/compiler-cli/ngcc');
|
|
||||||
private watchMode?: boolean;
|
private watchMode?: boolean;
|
||||||
private ngtscNextProgram?: NgtscProgram;
|
private ngtscNextProgram?: NgtscProgram;
|
||||||
private builder?: ts.EmitAndSemanticDiagnosticsBuilderProgram;
|
private builder?: ts.EmitAndSemanticDiagnosticsBuilderProgram;
|
||||||
@ -163,21 +123,13 @@ export class AngularWebpackPlugin {
|
|||||||
// Set resolver options
|
// Set resolver options
|
||||||
const pathsPlugin = new TypeScriptPathsPlugin();
|
const pathsPlugin = new TypeScriptPathsPlugin();
|
||||||
compiler.hooks.afterResolvers.tap(PLUGIN_NAME, (compiler) => {
|
compiler.hooks.afterResolvers.tap(PLUGIN_NAME, (compiler) => {
|
||||||
// When Ivy is enabled we need to add the fields added by NGCC
|
|
||||||
// to take precedence over the provided mainFields.
|
|
||||||
// NGCC adds fields in package.json suffixed with '_ivy_ngcc'
|
|
||||||
// Example: module -> module__ivy_ngcc
|
|
||||||
compiler.resolverFactory.hooks.resolveOptions
|
compiler.resolverFactory.hooks.resolveOptions
|
||||||
.for('normal')
|
.for('normal')
|
||||||
.tap(PLUGIN_NAME, (resolveOptions) => {
|
.tap(PLUGIN_NAME, (resolveOptions) => {
|
||||||
const originalMainFields = resolveOptions.mainFields;
|
|
||||||
const ivyMainFields = originalMainFields?.flat().map((f) => `${f}_ivy_ngcc`) ?? [];
|
|
||||||
|
|
||||||
resolveOptions.plugins ??= [];
|
resolveOptions.plugins ??= [];
|
||||||
resolveOptions.plugins.push(pathsPlugin);
|
resolveOptions.plugins.push(pathsPlugin);
|
||||||
|
|
||||||
// https://github.com/webpack/webpack/issues/11635#issuecomment-707016779
|
return resolveOptions;
|
||||||
return util.cleverMerge(resolveOptions, { mainFields: [...ivyMainFields, '...'] });
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -216,21 +168,6 @@ export class AngularWebpackPlugin {
|
|||||||
state.resourceLoader = new WebpackResourceLoader(this.watchMode);
|
state.resourceLoader = new WebpackResourceLoader(this.watchMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize and process eager ngcc if not already setup
|
|
||||||
if (!state.ngccProcessor) {
|
|
||||||
const { processor, errors, warnings } = initializeNgccProcessor(
|
|
||||||
compiler,
|
|
||||||
this.pluginOptions.tsconfig,
|
|
||||||
this.compilerNgccModule,
|
|
||||||
);
|
|
||||||
|
|
||||||
processor.process();
|
|
||||||
warnings.forEach((warning) => addWarning(compilation, warning));
|
|
||||||
errors.forEach((error) => addError(compilation, error));
|
|
||||||
|
|
||||||
state.ngccProcessor = processor;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup and read TypeScript and Angular compiler configuration
|
// Setup and read TypeScript and Angular compiler configuration
|
||||||
const { compilerOptions, rootNames, errors } = this.loadConfiguration();
|
const { compilerOptions, rootNames, errors } = this.loadConfiguration();
|
||||||
|
|
||||||
@ -284,9 +221,6 @@ export class AngularWebpackPlugin {
|
|||||||
// Setup source file dependency collection
|
// Setup source file dependency collection
|
||||||
augmentHostWithDependencyCollection(host, this.fileDependencies, moduleResolutionCache);
|
augmentHostWithDependencyCollection(host, this.fileDependencies, moduleResolutionCache);
|
||||||
|
|
||||||
// Setup on demand ngcc
|
|
||||||
augmentHostWithNgcc(host, state.ngccProcessor, moduleResolutionCache);
|
|
||||||
|
|
||||||
// Setup resource loading
|
// Setup resource loading
|
||||||
state.resourceLoader.update(compilation, changedFiles);
|
state.resourceLoader.update(compilation, changedFiles);
|
||||||
augmentHostWithResources(host, state.resourceLoader, {
|
augmentHostWithResources(host, state.resourceLoader, {
|
||||||
@ -760,7 +694,6 @@ export class AngularWebpackPlugin {
|
|||||||
// Once TypeScript provides support for keeping the dynamic import this workaround can
|
// Once TypeScript provides support for keeping the dynamic import this workaround can
|
||||||
// be dropped.
|
// be dropped.
|
||||||
this.compilerCliModule = await new Function(`return import('@angular/compiler-cli');`)();
|
this.compilerCliModule = await new Function(`return import('@angular/compiler-cli');`)();
|
||||||
this.compilerNgccModule = await new Function(`return import('@angular/compiler-cli/ngcc');`)();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async addFileEmitHistory(
|
private async addFileEmitHistory(
|
||||||
|
@ -1,304 +0,0 @@
|
|||||||
/**
|
|
||||||
* @license
|
|
||||||
* Copyright Google LLC All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
|
||||||
* found in the LICENSE file at https://angular.io/license
|
|
||||||
*/
|
|
||||||
|
|
||||||
import type { LogLevel, Logger } from '@angular/compiler-cli/ngcc';
|
|
||||||
import { spawnSync } from 'child_process';
|
|
||||||
import { createHash } from 'crypto';
|
|
||||||
import { accessSync, constants, existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
||||||
import * as path from 'path';
|
|
||||||
import * as ts from 'typescript';
|
|
||||||
import type { Compiler } from 'webpack';
|
|
||||||
import { time, timeEnd } from './benchmark';
|
|
||||||
import { InputFileSystem } from './ivy/system';
|
|
||||||
|
|
||||||
// Extract Resolver type from Webpack types since it is not directly exported
|
|
||||||
type ResolverWithOptions = ReturnType<Compiler['resolverFactory']['get']>;
|
|
||||||
|
|
||||||
// We cannot create a plugin for this, because NGTSC requires addition type
|
|
||||||
// information which ngcc creates when processing a package which was compiled with NGC.
|
|
||||||
|
|
||||||
// Example of such errors:
|
|
||||||
// ERROR in node_modules/@angular/platform-browser/platform-browser.d.ts(42,22):
|
|
||||||
// error TS-996002: Appears in the NgModule.imports of AppModule,
|
|
||||||
// but could not be resolved to an NgModule class
|
|
||||||
|
|
||||||
// We now transform a package and it's typings when NGTSC is resolving a module.
|
|
||||||
|
|
||||||
export class NgccProcessor {
|
|
||||||
private _processedModules = new Set<string>();
|
|
||||||
private _logger: NgccLogger;
|
|
||||||
private _nodeModulesDirectory: string | null;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private readonly compilerNgcc: typeof import('@angular/compiler-cli/ngcc'),
|
|
||||||
private readonly propertiesToConsider: string[],
|
|
||||||
private readonly compilationWarnings: (Error | string)[],
|
|
||||||
private readonly compilationErrors: (Error | string)[],
|
|
||||||
private readonly basePath: string,
|
|
||||||
private readonly tsConfigPath: string,
|
|
||||||
private readonly inputFileSystem: InputFileSystem,
|
|
||||||
private readonly resolver: ResolverWithOptions,
|
|
||||||
) {
|
|
||||||
this._logger = new NgccLogger(
|
|
||||||
this.compilationWarnings,
|
|
||||||
this.compilationErrors,
|
|
||||||
compilerNgcc.LogLevel.info,
|
|
||||||
);
|
|
||||||
this._nodeModulesDirectory = this.findNodeModulesDirectory(this.basePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Process the entire node modules tree. */
|
|
||||||
process() {
|
|
||||||
// Under Bazel when running in sandbox mode parts of the filesystem is read-only, or when using
|
|
||||||
// Yarn PnP there may not be a node_modules directory. ngcc can't run in those cases, so the
|
|
||||||
// processing is skipped.
|
|
||||||
if (process.env.BAZEL_TARGET || !this._nodeModulesDirectory) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip if node_modules are read-only
|
|
||||||
const corePackage = this.tryResolvePackage('@angular/core', this._nodeModulesDirectory);
|
|
||||||
if (corePackage && isReadOnlyFile(corePackage)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform a ngcc run check to determine if an initial execution is required.
|
|
||||||
// If a run hash file exists that matches the current package manager lock file and the
|
|
||||||
// project's tsconfig, then an initial ngcc run has already been performed.
|
|
||||||
let skipProcessing = false;
|
|
||||||
let runHashFilePath: string | undefined;
|
|
||||||
const runHashBasePath = path.join(this._nodeModulesDirectory, '.cli-ngcc');
|
|
||||||
const projectBasePath = path.join(this._nodeModulesDirectory, '..');
|
|
||||||
try {
|
|
||||||
let ngccConfigData;
|
|
||||||
try {
|
|
||||||
ngccConfigData = readFileSync(path.join(projectBasePath, 'ngcc.config.js'));
|
|
||||||
} catch {
|
|
||||||
ngccConfigData = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
const relativeTsconfigPath = path.relative(projectBasePath, this.tsConfigPath);
|
|
||||||
const tsconfigData = readFileSync(this.tsConfigPath);
|
|
||||||
const { lockFileData, lockFilePath } = this.findPackageManagerLockFile(projectBasePath);
|
|
||||||
|
|
||||||
// Generate a hash that represents the state of the package lock file and used tsconfig
|
|
||||||
const runHash = createHash('sha256')
|
|
||||||
.update(lockFileData)
|
|
||||||
.update(lockFilePath)
|
|
||||||
.update(ngccConfigData)
|
|
||||||
.update(tsconfigData)
|
|
||||||
.update(relativeTsconfigPath)
|
|
||||||
.digest('hex');
|
|
||||||
|
|
||||||
// The hash is used directly in the file name to mitigate potential read/write race
|
|
||||||
// conditions as well as to only require a file existence check
|
|
||||||
runHashFilePath = path.join(runHashBasePath, runHash + '.lock');
|
|
||||||
|
|
||||||
// If the run hash lock file exists, then ngcc was already run against this project state
|
|
||||||
if (existsSync(runHashFilePath)) {
|
|
||||||
skipProcessing = true;
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
// Any error means an ngcc execution is needed
|
|
||||||
}
|
|
||||||
|
|
||||||
if (skipProcessing) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const timeLabel = 'NgccProcessor.process';
|
|
||||||
time(timeLabel);
|
|
||||||
|
|
||||||
// We spawn instead of using the API because:
|
|
||||||
// - NGCC Async uses clustering which is problematic when used via the API which means
|
|
||||||
// that we cannot setup multiple cluster masters with different options.
|
|
||||||
// - We will not be able to have concurrent builds otherwise Ex: App-Shell,
|
|
||||||
// as NGCC will create a lock file for both builds and it will cause builds to fails.
|
|
||||||
const originalProcessTitle = process.title;
|
|
||||||
try {
|
|
||||||
const { status, error } = spawnSync(
|
|
||||||
process.execPath,
|
|
||||||
[
|
|
||||||
this.compilerNgcc.ngccMainFilePath,
|
|
||||||
'--source' /** basePath */,
|
|
||||||
this._nodeModulesDirectory,
|
|
||||||
'--properties' /** propertiesToConsider */,
|
|
||||||
...this.propertiesToConsider,
|
|
||||||
'--first-only' /** compileAllFormats */,
|
|
||||||
'--create-ivy-entry-points' /** createNewEntryPointFormats */,
|
|
||||||
'--async',
|
|
||||||
'--tsconfig' /** tsConfigPath */,
|
|
||||||
this.tsConfigPath,
|
|
||||||
'--use-program-dependencies',
|
|
||||||
],
|
|
||||||
{
|
|
||||||
stdio: ['inherit', process.stderr, process.stderr],
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (status !== 0) {
|
|
||||||
const errorMessage = error?.message || '';
|
|
||||||
throw new Error(errorMessage + `NGCC failed${errorMessage ? ', see above' : ''}.`);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
process.title = originalProcessTitle;
|
|
||||||
}
|
|
||||||
|
|
||||||
timeEnd(timeLabel);
|
|
||||||
|
|
||||||
// ngcc was successful so if a run hash was generated, write it for next time
|
|
||||||
if (runHashFilePath) {
|
|
||||||
try {
|
|
||||||
if (!existsSync(runHashBasePath)) {
|
|
||||||
mkdirSync(runHashBasePath, { recursive: true });
|
|
||||||
}
|
|
||||||
writeFileSync(runHashFilePath, '');
|
|
||||||
} catch {
|
|
||||||
// Errors are non-fatal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Process a module and its dependencies. */
|
|
||||||
processModule(
|
|
||||||
moduleName: string,
|
|
||||||
resolvedModule: ts.ResolvedModule | ts.ResolvedTypeReferenceDirective,
|
|
||||||
): void {
|
|
||||||
const resolvedFileName = resolvedModule.resolvedFileName;
|
|
||||||
if (
|
|
||||||
!this._nodeModulesDirectory ||
|
|
||||||
!resolvedFileName ||
|
|
||||||
moduleName.startsWith('.') ||
|
|
||||||
this._processedModules.has(resolvedFileName)
|
|
||||||
) {
|
|
||||||
// Skip when module_modules directory is not present, module is unknown, relative or the
|
|
||||||
// NGCC compiler is not found or already processed.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const packageJsonPath = this.tryResolvePackage(moduleName, resolvedFileName);
|
|
||||||
// If the package.json is read only we should skip calling NGCC.
|
|
||||||
// With Bazel when running under sandbox the filesystem is read-only.
|
|
||||||
if (!packageJsonPath || isReadOnlyFile(packageJsonPath)) {
|
|
||||||
// add it to processed so the second time round we skip this.
|
|
||||||
this._processedModules.add(resolvedFileName);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const timeLabel = `NgccProcessor.processModule.ngcc.process+${moduleName}`;
|
|
||||||
time(timeLabel);
|
|
||||||
this.compilerNgcc.process({
|
|
||||||
basePath: this._nodeModulesDirectory,
|
|
||||||
targetEntryPointPath: path.dirname(packageJsonPath),
|
|
||||||
propertiesToConsider: this.propertiesToConsider,
|
|
||||||
compileAllFormats: false,
|
|
||||||
createNewEntryPointFormats: true,
|
|
||||||
logger: this._logger,
|
|
||||||
tsConfigPath: this.tsConfigPath,
|
|
||||||
});
|
|
||||||
timeEnd(timeLabel);
|
|
||||||
|
|
||||||
// Purge this file from cache, since NGCC add new mainFields. Ex: module_ivy_ngcc
|
|
||||||
// which are unknown in the cached file.
|
|
||||||
this.inputFileSystem.purge?.(packageJsonPath);
|
|
||||||
|
|
||||||
this._processedModules.add(resolvedFileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
invalidate(fileName: string) {
|
|
||||||
this._processedModules.delete(fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Try resolve a package.json file from the resolved .d.ts file.
|
|
||||||
*/
|
|
||||||
private tryResolvePackage(moduleName: string, resolvedFileName: string): string | undefined {
|
|
||||||
try {
|
|
||||||
const resolvedPath = this.resolver.resolveSync(
|
|
||||||
{},
|
|
||||||
resolvedFileName,
|
|
||||||
`${moduleName}/package.json`,
|
|
||||||
);
|
|
||||||
|
|
||||||
return resolvedPath || undefined;
|
|
||||||
} catch {
|
|
||||||
// Ex: @angular/compiler/src/i18n/i18n_ast/package.json
|
|
||||||
// or local libraries which don't reside in node_modules
|
|
||||||
const packageJsonPath = path.resolve(resolvedFileName, '../package.json');
|
|
||||||
|
|
||||||
return existsSync(packageJsonPath) ? packageJsonPath : undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private findNodeModulesDirectory(startPoint: string): string | null {
|
|
||||||
let current = startPoint;
|
|
||||||
while (path.dirname(current) !== current) {
|
|
||||||
const nodePath = path.join(current, 'node_modules');
|
|
||||||
if (existsSync(nodePath)) {
|
|
||||||
return nodePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
current = path.dirname(current);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private findPackageManagerLockFile(projectBasePath: string): {
|
|
||||||
lockFilePath: string;
|
|
||||||
lockFileData: Buffer;
|
|
||||||
} {
|
|
||||||
for (const lockFile of ['yarn.lock', 'pnpm-lock.yaml', 'package-lock.json']) {
|
|
||||||
const lockFilePath = path.join(projectBasePath, lockFile);
|
|
||||||
|
|
||||||
try {
|
|
||||||
return {
|
|
||||||
lockFilePath,
|
|
||||||
lockFileData: readFileSync(lockFilePath),
|
|
||||||
};
|
|
||||||
} catch {}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error('Cannot locate a package manager lock file.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class NgccLogger implements Logger {
|
|
||||||
constructor(
|
|
||||||
private readonly compilationWarnings: (Error | string)[],
|
|
||||||
private readonly compilationErrors: (Error | string)[],
|
|
||||||
public level: LogLevel,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
||||||
debug() {}
|
|
||||||
|
|
||||||
info(...args: string[]) {
|
|
||||||
// Log to stderr because it's a progress-like info message.
|
|
||||||
process.stderr.write(`\n${args.join(' ')}\n`);
|
|
||||||
}
|
|
||||||
|
|
||||||
warn(...args: string[]) {
|
|
||||||
this.compilationWarnings.push(args.join(' '));
|
|
||||||
}
|
|
||||||
|
|
||||||
error(...args: string[]) {
|
|
||||||
this.compilationErrors.push(new Error(args.join(' ')));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function isReadOnlyFile(fileName: string): boolean {
|
|
||||||
try {
|
|
||||||
accessSync(fileName, constants.W_OK);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
} catch {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user