@@ -13,9 +13,78 @@ import {
13
13
AngularCompilerPlugin ,
14
14
AngularCompilerPluginOptions ,
15
15
NgToolsLoader ,
16
- PLATFORM
16
+ PLATFORM ,
17
+ ivy ,
17
18
} from '@ngtools/webpack' ;
18
19
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
+ }
19
88
20
89
function _pluginOptionsOverrides (
21
90
buildOptions : BuildOptions ,
@@ -103,40 +172,78 @@ function _createAotPlugin(
103
172
104
173
export function getNonAotConfig ( wco : WebpackConfigOptions ) {
105
174
const { tsConfigPath } = wco ;
175
+ const useIvyOnlyPlugin = canUseIvyPlugin ( wco ) ;
106
176
107
177
return {
108
- module : { rules : [ { test : / \. t s x ? $ / , loader : NgToolsLoader } ] } ,
109
- plugins : [ _createAotPlugin ( wco , { tsConfigPath, skipCodeGeneration : true } ) ]
178
+ module : {
179
+ rules : [
180
+ {
181
+ test : useIvyOnlyPlugin ? / \. [ j t ] s x ? $ / : / \. t s x ? $ / ,
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
+ ] ,
110
193
} ;
111
194
}
112
195
113
196
export function getAotConfig ( wco : WebpackConfigOptions , i18nExtract = false ) {
114
197
const { tsConfigPath, buildOptions } = wco ;
198
+ const optimize = buildOptions . optimization . scripts ;
199
+ const useIvyOnlyPlugin = canUseIvyPlugin ( wco ) && ! i18nExtract ;
115
200
116
- const loaders : any [ ] = [ NgToolsLoader ] ;
201
+ let buildOptimizerRules : RuleSetLoader [ ] = [ ] ;
117
202
if ( buildOptions . buildOptimizer ) {
118
- loaders . unshift ( {
203
+ buildOptimizerRules = [ {
119
204
loader : buildOptimizerLoaderPath ,
120
205
options : { sourceMap : buildOptions . sourceMap . scripts }
121
- } ) ;
206
+ } ] ;
122
207
}
123
208
124
- const test = / (?: \. n g f a c t o r y \. j s | \. n g s t y l e \. j s | \. t s x ? ) $ / ;
125
- const optimize = wco . buildOptions . optimization . scripts ;
126
-
127
209
return {
128
- module : { rules : [ { test, use : loaders } ] } ,
210
+ module : {
211
+ rules : [
212
+ {
213
+ test : useIvyOnlyPlugin ? / \. t s x ? $ / : / (?: \. n g f a c t o r y \. j s | \. n g s t y l e \. j s | \. t s x ? ) $ / ,
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 : / \. j s x ? $ / ,
224
+ use : [ ivy . AngularWebpackLoaderPath ] ,
225
+ } ,
226
+ ]
227
+ : [ ] ) ,
228
+ ] ,
229
+ } ,
129
230
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
+ ) ,
135
238
] ,
136
239
} ;
137
240
}
138
241
139
242
export function getTypescriptWorkerPlugin ( wco : WebpackConfigOptions , workerTsConfigPath : string ) {
243
+ if ( canUseIvyPlugin ( wco ) ) {
244
+ return createIvyPlugin ( wco , false , workerTsConfigPath ) ;
245
+ }
246
+
140
247
const { buildOptions } = wco ;
141
248
142
249
let pluginOptions : AngularCompilerPluginOptions = {
0 commit comments