Skip to content

refactor(@ngtools/webpack): remove NGCC integration #24720

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 0 additions & 62 deletions packages/ngtools/webpack/src/ivy/host.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import type { CompilerHost } from '@angular/compiler-cli';
import { createHash } from 'crypto';
import * as path from 'path';
import * as ts from 'typescript';
import { NgccProcessor } from '../ngcc_processor';
import { WebpackResourceLoader } from '../resource_loader';
import { normalizePath } from './paths';

Expand Down Expand Up @@ -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(
host: ts.CompilerHost,
replacements: Record<string, string>,
Expand Down
69 changes: 1 addition & 68 deletions packages/ngtools/webpack/src/ivy/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import type { CompilerHost, CompilerOptions, NgtscProgram } from '@angular/compi
import { strict as assert } from 'assert';
import * as ts from 'typescript';
import type { Compilation, Compiler, Module, NormalModule } from 'webpack';
import { NgccProcessor } from '../ngcc_processor';
import { TypeScriptPathsPlugin } from '../paths-plugin';
import { WebpackResourceLoader } from '../resource_loader';
import { SourceFileCache } from './cache';
Expand All @@ -23,7 +22,6 @@ import {
import {
augmentHostWithCaching,
augmentHostWithDependencyCollection,
augmentHostWithNgcc,
augmentHostWithReplacements,
augmentHostWithResources,
augmentHostWithSubstitutions,
Expand Down Expand Up @@ -57,48 +55,11 @@ export interface AngularWebpackPluginOptions {
* The Angular compilation state that is maintained across each Webpack compilation.
*/
interface AngularCompilationState {
ngccProcessor?: NgccProcessor;
resourceLoader?: WebpackResourceLoader;
previousUnused?: Set<string>;
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 compilationFileEmitters = new WeakMap<Compilation, FileEmitterCollection>();

Expand All @@ -110,7 +71,6 @@ interface FileEmitHistoryItem {
export class AngularWebpackPlugin {
private readonly pluginOptions: AngularWebpackPluginOptions;
private compilerCliModule?: typeof import('@angular/compiler-cli');
private compilerNgccModule?: typeof import('@angular/compiler-cli/ngcc');
private watchMode?: boolean;
private ngtscNextProgram?: NgtscProgram;
private builder?: ts.EmitAndSemanticDiagnosticsBuilderProgram;
Expand Down Expand Up @@ -163,21 +123,13 @@ export class AngularWebpackPlugin {
// Set resolver options
const pathsPlugin = new TypeScriptPathsPlugin();
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
.for('normal')
.tap(PLUGIN_NAME, (resolveOptions) => {
const originalMainFields = resolveOptions.mainFields;
const ivyMainFields = originalMainFields?.flat().map((f) => `${f}_ivy_ngcc`) ?? [];

resolveOptions.plugins ??= [];
resolveOptions.plugins.push(pathsPlugin);

// https://github.com/webpack/webpack/issues/11635#issuecomment-707016779
return util.cleverMerge(resolveOptions, { mainFields: [...ivyMainFields, '...'] });
return resolveOptions;
});
});

Expand Down Expand Up @@ -216,21 +168,6 @@ export class AngularWebpackPlugin {
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
const { compilerOptions, rootNames, errors } = this.loadConfiguration();

Expand Down Expand Up @@ -284,9 +221,6 @@ export class AngularWebpackPlugin {
// Setup source file dependency collection
augmentHostWithDependencyCollection(host, this.fileDependencies, moduleResolutionCache);

// Setup on demand ngcc
augmentHostWithNgcc(host, state.ngccProcessor, moduleResolutionCache);

// Setup resource loading
state.resourceLoader.update(compilation, changedFiles);
augmentHostWithResources(host, state.resourceLoader, {
Expand Down Expand Up @@ -760,7 +694,6 @@ export class AngularWebpackPlugin {
// Once TypeScript provides support for keeping the dynamic import this workaround can
// be dropped.
this.compilerCliModule = await new Function(`return import('@angular/compiler-cli');`)();
this.compilerNgccModule = await new Function(`return import('@angular/compiler-cli/ngcc');`)();
}

private async addFileEmitHistory(
Expand Down
Loading