Skip to content

Commit

Permalink
fix(@angular-devkit/build-angular): remove usage of deprecated View E…
Browse files Browse the repository at this point in the history
…ngine compiler

BREAKING CHANGE: Removal of View Engine support from application builds
With the removal of the deprecated View Engine compiler in Angular version 12 for applications, Ivy-based compilation will always be used when building an application.
The default behavior for applications is to use the Ivy compiler when building and no changes are required for these applications.
For applications that have opted-out of Ivy, a warning will be shown and an Ivy-based build will be attempted. If the build fails,
the application may need to be updated to become Ivy compatible.
  • Loading branch information
clydin authored and alan-agius4 committed Apr 2, 2021
1 parent f6759c0 commit 677913f
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 153 deletions.
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

0 comments on commit 677913f

Please sign in to comment.