Skip to content
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

Remove ESM workarounds #22299

Merged
merged 2 commits into from
Dec 6, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import type { ɵParsedTranslation } from '@angular/localize/private';
import type {
DiagnosticHandlingStrategy,
Diagnostics,
Expand Down Expand Up @@ -35,9 +36,9 @@ export interface ApplicationPresetOptions {
i18n?: {
locale: string;
missingTranslationBehavior?: 'error' | 'warning' | 'ignore';
translation?: unknown;
translation?: Record<string, ɵParsedTranslation>;
translationFiles?: string[];
pluginCreators?: I18nPluginCreators;
pluginCreators: I18nPluginCreators;
};

angularLinker?: {
Expand Down Expand Up @@ -107,47 +108,30 @@ function createI18nDiagnostics(reporter: DiagnosticReporter | undefined): Diagno

function createI18nPlugins(
locale: string,
translation: unknown | undefined,
translation: Record<string, ɵParsedTranslation> | undefined,
missingTranslationBehavior: 'error' | 'warning' | 'ignore',
diagnosticReporter: DiagnosticReporter | undefined,
// TODO_ESM: Make `pluginCreators` required once `@angular/localize` is published with the `tools` entry point
pluginCreators: I18nPluginCreators | undefined,
pluginCreators: I18nPluginCreators,
) {
const diagnostics = createI18nDiagnostics(diagnosticReporter);
const plugins = [];

const { makeEs5TranslatePlugin, makeEs2015TranslatePlugin, makeLocalePlugin } = pluginCreators;

if (translation) {
const {
makeEs2015TranslatePlugin,
// TODO_ESM: Remove all deep imports once `@angular/localize` is published with the `tools` entry point
} =
pluginCreators ??
require('@angular/localize/src/tools/src/translate/source_files/es2015_translate_plugin');
plugins.push(
makeEs2015TranslatePlugin(diagnostics, translation, {
missingTranslation: missingTranslationBehavior,
}),
);

const {
makeEs5TranslatePlugin,
// TODO_ESM: Remove all deep imports once `@angular/localize` is published with the `tools` entry point
} =
pluginCreators ??
require('@angular/localize/src/tools/src/translate/source_files/es5_translate_plugin');
plugins.push(
makeEs5TranslatePlugin(diagnostics, translation, {
missingTranslation: missingTranslationBehavior,
}),
);
}

const {
makeLocalePlugin,
// TODO_ESM: Remove all deep imports once `@angular/localize` is published with the `tools` entry point
} =
pluginCreators ??
require('@angular/localize/src/tools/src/translate/source_files/locale_plugin');
plugins.push(makeLocalePlugin(locale));

return plugins;
Expand Down
22 changes: 9 additions & 13 deletions packages/angular_devkit/build_angular/src/babel/webpack-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,14 @@ export default custom<ApplicationPresetOptions>(() => {

// Analyze file for linking
if (await requiresLinking(this.resourcePath, source)) {
if (!linkerPluginCreator) {
// Load ESM `@angular/compiler-cli/linker/babel` using the TypeScript dynamic import workaround.
// Once TypeScript provides support for keeping the dynamic import this workaround can be
// changed to a direct dynamic import.
const linkerBabelModule = await loadEsmModule<
typeof import('@angular/compiler-cli/linker/babel')
>('@angular/compiler-cli/linker/babel');
linkerPluginCreator = linkerBabelModule.createEs2015LinkerPlugin;
}
// Load ESM `@angular/compiler-cli/linker/babel` using the TypeScript dynamic import workaround.
// Once TypeScript provides support for keeping the dynamic import this workaround can be
// changed to a direct dynamic import.
linkerPluginCreator ??= (
await loadEsmModule<typeof import('@angular/compiler-cli/linker/babel')>(
'@angular/compiler-cli/linker/babel',
)
).createEs2015LinkerPlugin;

customOptions.angularLinker = {
shouldLink: true,
Expand Down Expand Up @@ -136,14 +135,11 @@ export default custom<ApplicationPresetOptions>(() => {
// During the transition, this will always attempt to load the entry point for each file.
// This will only occur during prerelease and will be automatically corrected once the new
// entry point exists.
// TODO_ESM: Make import failure an error once the `tools` entry point exists.
if (i18nPluginCreators === undefined) {
// Load ESM `@angular/localize/tools` using the TypeScript dynamic import workaround.
// Once TypeScript provides support for keeping the dynamic import this workaround can be
// changed to a direct dynamic import.
try {
i18nPluginCreators = await loadEsmModule<I18nPluginCreators>('@angular/localize/tools');
} catch {}
i18nPluginCreators = await loadEsmModule<I18nPluginCreators>('@angular/localize/tools');
alan-agius4 marked this conversation as resolved.
Show resolved Hide resolved
}

customOptions.i18n = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ async function extract(
// Try to load the `@angular/localize` message extractor.
// All the localize usages are setup to first try the ESM entry point then fallback to the deep imports.
// This provides interim compatibility while the framework is transitioned to bundled ESM packages.
// TODO_ESM: Remove all deep imports once `@angular/localize` is published with the `tools` entry point
let MessageExtractor;
try {
// Load ESM `@angular/localize/tools` using the TypeScript dynamic import workaround.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,9 +217,7 @@ export async function configureI18nBuild<T extends BrowserBuilderSchema | Server
continue;
}

if (!loader) {
loader = await createTranslationLoader();
}
loader ??= await createTranslationLoader();

loadTranslations(
locale,
Expand Down
11 changes: 3 additions & 8 deletions packages/angular_devkit/build_angular/src/utils/read-tsconfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,9 @@ export async function readTsconfig(
// Load ESM `@angular/compiler-cli` using the TypeScript dynamic import workaround.
// Once TypeScript provides support for keeping the dynamic import this workaround can be
// changed to a direct dynamic import.
const compilerCliModule = await loadEsmModule<{ readConfiguration: unknown; default: unknown }>(
'@angular/compiler-cli',
);
// If it is not ESM then the functions needed will be stored in the `default` property.
// TODO_ESM: This can be removed once `@angular/compiler-cli` is ESM only.
const { formatDiagnostics, readConfiguration } = (
compilerCliModule.readConfiguration ? compilerCliModule : compilerCliModule.default
) as typeof import('@angular/compiler-cli');
const { formatDiagnostics, readConfiguration } = await loadEsmModule<
typeof import('@angular/compiler-cli')
>('@angular/compiler-cli');

const configResult = readConfiguration(tsConfigFullPath);
if (configResult.errors && configResult.errors.length) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,19 +82,11 @@ export async function getCommonConfig(wco: WebpackConfigOptions): Promise<Config
// Load ESM `@angular/compiler-cli` using the TypeScript dynamic import workaround.
// Once TypeScript provides support for keeping the dynamic import this workaround can be
// changed to a direct dynamic import.
const compilerCliModule = await loadEsmModule<{
GLOBAL_DEFS_FOR_TERSER: unknown;
default: unknown;
}>('@angular/compiler-cli');
// If it is not ESM then the values needed will be stored in the `default` property.
// TODO_ESM: This can be removed once `@angular/compiler-cli` is ESM only.
const {
GLOBAL_DEFS_FOR_TERSER,
GLOBAL_DEFS_FOR_TERSER_WITH_AOT,
VERSION: NG_VERSION,
} = (
compilerCliModule.GLOBAL_DEFS_FOR_TERSER ? compilerCliModule : compilerCliModule.default
) as typeof import('@angular/compiler-cli');
} = await loadEsmModule<typeof import('@angular/compiler-cli')>('@angular/compiler-cli');

// determine hashing format
const hashFormat = getOutputHashFormat(buildOptions.outputHashing || 'none');
Expand Down
21 changes: 2 additions & 19 deletions packages/ngtools/webpack/src/ivy/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -734,24 +734,7 @@ export class AngularWebpackPlugin {
// this, a Function constructor is used to prevent TypeScript from changing the dynamic import.
// Once TypeScript provides support for keeping the dynamic import this workaround can
// be dropped.
const compilerCliModule = await new Function(`return import('@angular/compiler-cli');`)();
let compilerNgccModule;
try {
compilerNgccModule = await new Function(`return import('@angular/compiler-cli/ngcc');`)();
} catch {
// If the `exports` field entry is not present then try the file directly.
// TODO_ESM: This try/catch can be removed once the `exports` field is present in `@angular/compiler-cli`
compilerNgccModule = await new Function(
`return import('@angular/compiler-cli/ngcc/index.js');`,
)();
}
// If it is not ESM then the functions needed will be stored in the `default` property.
// TODO_ESM: This conditional can be removed when `@angular/compiler-cli` is ESM only.
this.compilerCliModule = compilerCliModule.readConfiguration
? compilerCliModule
: compilerCliModule.default;
this.compilerNgccModule = compilerNgccModule.process
? compilerNgccModule
: compilerNgccModule.default;
this.compilerCliModule = await new Function(`return import('@angular/compiler-cli');`)();
this.compilerNgccModule = await new Function(`return import('@angular/compiler-cli/ngcc');`)();
}
}
10 changes: 1 addition & 9 deletions packages/ngtools/webpack/src/ngcc_processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,14 +120,6 @@ export class NgccProcessor {
const timeLabel = 'NgccProcessor.process';
time(timeLabel);

// Temporary workaround during transition to ESM-only @angular/compiler-cli
// TODO_ESM: This workaround should be removed prior to the final release of v13
// and replaced with only `this.compilerNgcc.ngccMainFilePath`.
const ngccExecutablePath =
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(this.compilerNgcc as any).ngccMainFilePath ??
require.resolve('@angular/compiler-cli/ngcc/main-ngcc.js');

// 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.
Expand All @@ -136,7 +128,7 @@ export class NgccProcessor {
const { status, error } = spawnSync(
process.execPath,
[
ngccExecutablePath,
this.compilerNgcc.ngccMainFilePath,
'--source' /** basePath */,
this._nodeModulesDirectory,
'--properties' /** propertiesToConsider */,
Expand Down