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

fix(@angular-devkit/build-angular): remove usage of deprecated View Engine compiler #20434

Merged
merged 1 commit into from
Apr 2, 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 @@ -82,8 +82,3 @@ export const cachingBasePath = (() => {
// Build profiling
const profilingVariable = process.env['NG_BUILD_PROFILING'];
export const profilingEnabled = isPresent(profilingVariable) && isEnabled(profilingVariable);

// Legacy Webpack plugin with Ivy
const legacyIvyVariable = process.env['NG_BUILD_IVY_LEGACY'];
export const legacyIvyPluginEnabled =
isPresent(legacyIvyVariable) && !isDisabled(legacyIvyVariable);
174 changes: 27 additions & 147 deletions packages/angular_devkit/build_angular/src/webpack/configs/typescript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,38 +5,25 @@
* 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
*/
// tslint:disable
// TODO: cleanup this file, it's copied as is from Angular CLI.
import { CompilerOptions } from '@angular/compiler-cli';
import { buildOptimizerLoaderPath } from '@angular-devkit/build-optimizer';
import { getSystemPath } from '@angular-devkit/core';
import {
AngularCompilerPlugin,
AngularCompilerPluginOptions,
NgToolsLoader,
PLATFORM,
ivy,
} from '@ngtools/webpack';
import * as path from 'path';
import { WebpackConfigOptions, BuildOptions } from '../../utils/build-options';
import { legacyIvyPluginEnabled } from '../../utils/environment-options';
import { CompilerOptions } from '@angular/compiler-cli';
import { ivy } from '@ngtools/webpack';
import { WebpackConfigOptions } from '../../utils/build-options';

function canUseIvyPlugin(wco: WebpackConfigOptions): boolean {
// Can only be used with Ivy
if (!wco.tsConfig.options.enableIvy) {
return false;
function ensureIvy(wco: WebpackConfigOptions): void {
if (wco.tsConfig.options.enableIvy !== false) {
return;
}

// Allow fallback to legacy build system via environment variable ('NG_BUILD_IVY_LEGACY=1')
if (legacyIvyPluginEnabled) {
wco.logger.warn(
'"NG_BUILD_IVY_LEGACY" environment variable detected. Using legacy Ivy build system.',
);

return false;
}
wco.logger.warn(
'Project is attempting to disable the Ivy compiler. ' +
'Angular versions 12 and higher do not support the deprecated View Engine compiler for applications. ' +
'The Ivy compiler will be used to build this project. ' +
'\nFor additional information or if the build fails, please see https://angular.io/guide/ivy',
);

return true;
wco.tsConfig.options.enableIvy = true;
}

function createIvyPlugin(
Expand Down Expand Up @@ -73,111 +60,34 @@ function createIvyPlugin(
});
}

function _pluginOptionsOverrides(
buildOptions: BuildOptions,
pluginOptions: AngularCompilerPluginOptions
): AngularCompilerPluginOptions {
const compilerOptions = {
...(pluginOptions.compilerOptions || {})
}

const hostReplacementPaths: { [replace: string]: string } = {};
if (buildOptions.fileReplacements) {
for (const replacement of buildOptions.fileReplacements) {
hostReplacementPaths[replacement.replace] = replacement.with;
}
}

if (buildOptions.preserveSymlinks) {
compilerOptions.preserveSymlinks = true;
}

return {
...pluginOptions,
hostReplacementPaths,
compilerOptions
};
}

function _createAotPlugin(
wco: WebpackConfigOptions,
options: AngularCompilerPluginOptions,
i18nExtract = false,
) {
const { root, buildOptions } = wco;

const i18nInFile = buildOptions.i18nFile
? path.resolve(root, buildOptions.i18nFile)
: undefined;

const i18nFileAndFormat = i18nExtract
? {
i18nOutFile: buildOptions.i18nFile,
i18nOutFormat: buildOptions.i18nFormat,
} : {
i18nInFile: i18nInFile,
i18nInFormat: buildOptions.i18nFormat,
};

const compilerOptions = options.compilerOptions || {};
if (i18nExtract) {
// Extraction of i18n is still using the legacy VE pipeline
compilerOptions.enableIvy = false;
}

let pluginOptions: AngularCompilerPluginOptions = {
mainPath: path.join(root, buildOptions.main),
...i18nFileAndFormat,
locale: buildOptions.i18nLocale,
platform: buildOptions.platform === 'server' ? PLATFORM.Server : PLATFORM.Browser,
missingTranslation: buildOptions.i18nMissingTranslation,
sourceMap: buildOptions.sourceMap.scripts,
nameLazyFiles: buildOptions.namedChunks,
forkTypeChecker: buildOptions.forkTypeChecker,
logger: wco.logger,
directTemplateLoading: true,
...options,
compilerOptions,
};

pluginOptions = _pluginOptionsOverrides(buildOptions, pluginOptions);

return new AngularCompilerPlugin(pluginOptions);
}

export function getNonAotConfig(wco: WebpackConfigOptions) {
const { tsConfigPath } = wco;
const useIvyOnlyPlugin = canUseIvyPlugin(wco);

return {
module: {
rules: [
{
test: useIvyOnlyPlugin ? /\.[jt]sx?$/ : /\.tsx?$/,
loader: useIvyOnlyPlugin
? ivy.AngularWebpackLoaderPath
: NgToolsLoader,
test: /\.[jt]sx?$/,
loader: ivy.AngularWebpackLoaderPath,
},
],
},
plugins: [
useIvyOnlyPlugin
? createIvyPlugin(wco, false, tsConfigPath)
: _createAotPlugin(wco, { tsConfigPath, skipCodeGeneration: true }),
createIvyPlugin(wco, false, tsConfigPath),
],
};
}

export function getAotConfig(wco: WebpackConfigOptions, i18nExtract = false) {
export function getAotConfig(wco: WebpackConfigOptions) {
const { tsConfigPath, buildOptions } = wco;
const optimize = buildOptions.optimization.scripts;
const useIvyOnlyPlugin = canUseIvyPlugin(wco) && !i18nExtract;

ensureIvy(wco);

return {
module: {
rules: [
{
test: useIvyOnlyPlugin ? /\.tsx?$/ : /(?:\.ngfactory\.js|\.ngstyle\.js|\.tsx?)$/,
test: /\.tsx?$/,
use: [
...(buildOptions.buildOptimizer
? [
Expand All @@ -187,52 +97,22 @@ export function getAotConfig(wco: WebpackConfigOptions, i18nExtract = false) {
},
]
: []),
useIvyOnlyPlugin ? ivy.AngularWebpackLoaderPath : NgToolsLoader,
ivy.AngularWebpackLoaderPath,
],
},
// "allowJs" support with ivy plugin - ensures build optimizer is not run twice
...(useIvyOnlyPlugin
? [
{
test: /\.jsx?$/,
use: [ivy.AngularWebpackLoaderPath],
},
]
: []),
{
test: /\.jsx?$/,
use: [ivy.AngularWebpackLoaderPath],
},
],
},
plugins: [
useIvyOnlyPlugin
? createIvyPlugin(wco, true, tsConfigPath)
: _createAotPlugin(
wco,
{ tsConfigPath, emitClassMetadata: !optimize, emitNgModuleScope: !optimize },
i18nExtract,
),
createIvyPlugin(wco, true, tsConfigPath),
],
};
}

export function getTypescriptWorkerPlugin(wco: WebpackConfigOptions, workerTsConfigPath: string) {
if (canUseIvyPlugin(wco)) {
return createIvyPlugin(wco, false, workerTsConfigPath);
}

const { buildOptions } = wco;

let pluginOptions: AngularCompilerPluginOptions = {
skipCodeGeneration: true,
tsConfigPath: workerTsConfigPath,
mainPath: undefined,
platform: PLATFORM.Browser,
sourceMap: buildOptions.sourceMap.scripts,
forkTypeChecker: buildOptions.forkTypeChecker,
logger: wco.logger,
// Run no transformers.
platformTransformers: [],
};

pluginOptions = _pluginOptionsOverrides(buildOptions, pluginOptions);

return new AngularCompilerPlugin(pluginOptions);
return createIvyPlugin(wco, false, workerTsConfigPath);
}
2 changes: 1 addition & 1 deletion tests/legacy-cli/e2e/tests/i18n/extract-ivy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export default async function() {
});

// Should show ivy disabled application warning with enableIvy false
const { message: message4 } = await expectToFail(() => ng('extract-i18n'));
const { stderr: message4 } = await ng('extract-i18n');
if (!message4.includes(`Ivy extraction enabled but application is not Ivy enabled.`)) {
throw new Error('Expected ivy disabled application warning');
}
Expand Down