Skip to content

Commit 97f9cbb

Browse files
committed
refactor(@angular-devkit/build-angular): integrate ivy-only compiler plugin
1 parent d378f6f commit 97f9cbb

File tree

1 file changed

+122
-15
lines changed
  • packages/angular_devkit/build_angular/src/webpack/configs

1 file changed

+122
-15
lines changed

packages/angular_devkit/build_angular/src/webpack/configs/typescript.ts

+122-15
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,78 @@ import {
1313
AngularCompilerPlugin,
1414
AngularCompilerPluginOptions,
1515
NgToolsLoader,
16-
PLATFORM
16+
PLATFORM,
17+
ivy,
1718
} from '@ngtools/webpack';
1819
import { WebpackConfigOptions, BuildOptions } from '../../utils/build-options';
20+
import { CompilerOptions } from '@angular/compiler-cli';
21+
import { RuleSetLoader } from 'webpack';
22+
23+
function canUseIvyPlugin(wco: WebpackConfigOptions): boolean {
24+
// Can only be used with Ivy
25+
if (!wco.tsConfig.options.enableIvy) {
26+
return false;
27+
}
28+
29+
// Allow fallback to legacy build system via environment variable ('NG_BUILD_IVY_LEGACY=1')
30+
const flag = process.env['NG_BUILD_IVY_LEGACY'];
31+
if (flag !== undefined && flag !== '0' && flag.toLowerCase() !== 'false') {
32+
wco.logger.warn(
33+
'"NG_BUILD_IVY_LEGACY" environment variable detected. Using legacy Ivy build system.',
34+
);
35+
36+
return false;
37+
}
38+
39+
// Lazy modules option uses the deprecated string format for lazy routes which is not supported
40+
if (wco.buildOptions.lazyModules && wco.buildOptions.lazyModules.length > 0) {
41+
wco.logger.warn(
42+
'"lazyModules" option is deprecated and not supported by the new Ivy build system. ' +
43+
'Using legacy Ivy build system.'
44+
);
45+
46+
return false;
47+
}
48+
49+
// This pass relies on internals of the original plugin
50+
if (wco.buildOptions.experimentalRollupPass) {
51+
return false;
52+
}
53+
54+
return true;
55+
}
56+
57+
function createIvyPlugin(
58+
wco: WebpackConfigOptions,
59+
aot: boolean,
60+
tsconfig: string,
61+
): ivy.AngularWebpackPlugin {
62+
const { buildOptions } = wco;
63+
const optimize = buildOptions.optimization.scripts;
64+
65+
const compilerOptions: CompilerOptions = {
66+
skipTemplateCodegen: !aot,
67+
sourceMap: buildOptions.sourceMap.scripts,
68+
};
69+
70+
if (buildOptions.preserveSymlinks !== undefined) {
71+
compilerOptions.preserveSymlinks = buildOptions.preserveSymlinks;
72+
}
73+
74+
const fileReplacements: Record<string, string> = {};
75+
if (buildOptions.fileReplacements) {
76+
for (const replacement of buildOptions.fileReplacements) {
77+
fileReplacements[replacement.replace] = replacement.with;
78+
}
79+
}
80+
81+
return new ivy.AngularWebpackPlugin({
82+
tsconfig,
83+
compilerOptions,
84+
fileReplacements,
85+
emitNgModuleScope: !optimize,
86+
});
87+
}
1988

2089
function _pluginOptionsOverrides(
2190
buildOptions: BuildOptions,
@@ -103,40 +172,78 @@ function _createAotPlugin(
103172

104173
export function getNonAotConfig(wco: WebpackConfigOptions) {
105174
const { tsConfigPath } = wco;
175+
const useIvyOnlyPlugin = canUseIvyPlugin(wco);
106176

107177
return {
108-
module: { rules: [{ test: /\.tsx?$/, loader: NgToolsLoader }] },
109-
plugins: [_createAotPlugin(wco, { tsConfigPath, skipCodeGeneration: true })]
178+
module: {
179+
rules: [
180+
{
181+
test: useIvyOnlyPlugin ? /\.[jt]sx?$/ : /\.tsx?$/,
182+
loader: useIvyOnlyPlugin
183+
? ivy.AngularWebpackLoaderPath
184+
: NgToolsLoader,
185+
},
186+
],
187+
},
188+
plugins: [
189+
useIvyOnlyPlugin
190+
? createIvyPlugin(wco, false, tsConfigPath)
191+
: _createAotPlugin(wco, { tsConfigPath, skipCodeGeneration: true }),
192+
],
110193
};
111194
}
112195

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

116-
const loaders: any[] = [NgToolsLoader];
201+
let buildOptimizerRules: RuleSetLoader[] = [];
117202
if (buildOptions.buildOptimizer) {
118-
loaders.unshift({
203+
buildOptimizerRules = [{
119204
loader: buildOptimizerLoaderPath,
120205
options: { sourceMap: buildOptions.sourceMap.scripts }
121-
});
206+
}];
122207
}
123208

124-
const test = /(?:\.ngfactory\.js|\.ngstyle\.js|\.tsx?)$/;
125-
const optimize = wco.buildOptions.optimization.scripts;
126-
127209
return {
128-
module: { rules: [{ test, use: loaders }] },
210+
module: {
211+
rules: [
212+
{
213+
test: useIvyOnlyPlugin ? /\.tsx?$/ : /(?:\.ngfactory\.js|\.ngstyle\.js|\.tsx?)$/,
214+
use: [
215+
...buildOptimizerRules,
216+
useIvyOnlyPlugin ? ivy.AngularWebpackLoaderPath : NgToolsLoader,
217+
],
218+
},
219+
// "allowJs" support with ivy plugin - ensures build optimizer is not run twice
220+
...(useIvyOnlyPlugin
221+
? [
222+
{
223+
test: /\.jsx?$/,
224+
use: [ivy.AngularWebpackLoaderPath],
225+
},
226+
]
227+
: []),
228+
],
229+
},
129230
plugins: [
130-
_createAotPlugin(
131-
wco,
132-
{ tsConfigPath, emitClassMetadata: !optimize, emitNgModuleScope: !optimize },
133-
i18nExtract,
134-
),
231+
useIvyOnlyPlugin
232+
? createIvyPlugin(wco, true, tsConfigPath)
233+
: _createAotPlugin(
234+
wco,
235+
{ tsConfigPath, emitClassMetadata: !optimize, emitNgModuleScope: !optimize },
236+
i18nExtract,
237+
),
135238
],
136239
};
137240
}
138241

139242
export function getTypescriptWorkerPlugin(wco: WebpackConfigOptions, workerTsConfigPath: string) {
243+
if (canUseIvyPlugin(wco)) {
244+
return createIvyPlugin(wco, false, workerTsConfigPath);
245+
}
246+
140247
const { buildOptions } = wco;
141248

142249
let pluginOptions: AngularCompilerPluginOptions = {

0 commit comments

Comments
 (0)