@@ -13,9 +13,73 @@ 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
40
+ if ( wco . buildOptions . lazyModules && wco . buildOptions . lazyModules . length > 0 ) {
41
+ return false ;
42
+ }
43
+
44
+ // This pass relies on internals of the original plugin
45
+ if ( wco . buildOptions . experimentalRollupPass ) {
46
+ return false ;
47
+ }
48
+
49
+ return true ;
50
+ }
51
+
52
+ function createIvyPlugin (
53
+ wco : WebpackConfigOptions ,
54
+ aot : boolean ,
55
+ tsconfig : string ,
56
+ ) : ivy . AngularWebpackPlugin {
57
+ const { buildOptions } = wco ;
58
+ const optimize = buildOptions . optimization . scripts ;
59
+
60
+ const compilerOptions : CompilerOptions = {
61
+ skipTemplateCodegen : ! aot ,
62
+ sourceMap : buildOptions . sourceMap . scripts ,
63
+ } ;
64
+
65
+ if ( buildOptions . preserveSymlinks !== undefined ) {
66
+ compilerOptions . preserveSymlinks = buildOptions . preserveSymlinks ;
67
+ }
68
+
69
+ const fileReplacements : Record < string , string > = { } ;
70
+ if ( buildOptions . fileReplacements ) {
71
+ for ( const replacement of buildOptions . fileReplacements ) {
72
+ fileReplacements [ replacement . replace ] = replacement . with ;
73
+ }
74
+ }
75
+
76
+ return new ivy . AngularWebpackPlugin ( {
77
+ tsconfig,
78
+ compilerOptions,
79
+ fileReplacements,
80
+ emitNgModuleScope : ! optimize ,
81
+ } ) ;
82
+ }
19
83
20
84
function _pluginOptionsOverrides (
21
85
buildOptions : BuildOptions ,
@@ -103,40 +167,78 @@ function _createAotPlugin(
103
167
104
168
export function getNonAotConfig ( wco : WebpackConfigOptions ) {
105
169
const { tsConfigPath } = wco ;
170
+ const useIvyOnlyPlugin = canUseIvyPlugin ( wco ) ;
106
171
107
172
return {
108
- module : { rules : [ { test : / \. t s x ? $ / , loader : NgToolsLoader } ] } ,
109
- plugins : [ _createAotPlugin ( wco , { tsConfigPath, skipCodeGeneration : true } ) ]
173
+ module : {
174
+ rules : [
175
+ {
176
+ test : useIvyOnlyPlugin ? / \. [ j t ] s x ? $ / : / \. t s x ? $ / ,
177
+ loader : useIvyOnlyPlugin
178
+ ? ivy . AngularWebpackLoaderPath
179
+ : NgToolsLoader ,
180
+ } ,
181
+ ] ,
182
+ } ,
183
+ plugins : [
184
+ useIvyOnlyPlugin
185
+ ? createIvyPlugin ( wco , false , tsConfigPath )
186
+ : _createAotPlugin ( wco , { tsConfigPath, skipCodeGeneration : true } ) ,
187
+ ] ,
110
188
} ;
111
189
}
112
190
113
191
export function getAotConfig ( wco : WebpackConfigOptions , i18nExtract = false ) {
114
192
const { tsConfigPath, buildOptions } = wco ;
193
+ const optimize = buildOptions . optimization . scripts ;
194
+ const useIvyOnlyPlugin = canUseIvyPlugin ( wco ) && ! i18nExtract ;
115
195
116
- const loaders : any [ ] = [ NgToolsLoader ] ;
196
+ let buildOptimizerRules : RuleSetLoader [ ] = [ ] ;
117
197
if ( buildOptions . buildOptimizer ) {
118
- loaders . unshift ( {
198
+ buildOptimizerRules = [ {
119
199
loader : buildOptimizerLoaderPath ,
120
200
options : { sourceMap : buildOptions . sourceMap . scripts }
121
- } ) ;
201
+ } ] ;
122
202
}
123
203
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
204
return {
128
- module : { rules : [ { test, use : loaders } ] } ,
205
+ module : {
206
+ rules : [
207
+ {
208
+ 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 ? ) $ / ,
209
+ use : [
210
+ ...buildOptimizerRules ,
211
+ useIvyOnlyPlugin ? ivy . AngularWebpackLoaderPath : NgToolsLoader ,
212
+ ] ,
213
+ } ,
214
+ // "allowJs" support with ivy plugin - ensures build optimizer is not run twice
215
+ ...( useIvyOnlyPlugin
216
+ ? [
217
+ {
218
+ test : / \. j s x ? $ / ,
219
+ use : [ ivy . AngularWebpackLoaderPath ] ,
220
+ } ,
221
+ ]
222
+ : [ ] ) ,
223
+ ] ,
224
+ } ,
129
225
plugins : [
130
- _createAotPlugin (
131
- wco ,
132
- { tsConfigPath, emitClassMetadata : ! optimize , emitNgModuleScope : ! optimize } ,
133
- i18nExtract ,
134
- ) ,
226
+ useIvyOnlyPlugin
227
+ ? createIvyPlugin ( wco , true , tsConfigPath )
228
+ : _createAotPlugin (
229
+ wco ,
230
+ { tsConfigPath, emitClassMetadata : ! optimize , emitNgModuleScope : ! optimize } ,
231
+ i18nExtract ,
232
+ ) ,
135
233
] ,
136
234
} ;
137
235
}
138
236
139
237
export function getTypescriptWorkerPlugin ( wco : WebpackConfigOptions , workerTsConfigPath : string ) {
238
+ if ( canUseIvyPlugin ( wco ) ) {
239
+ return createIvyPlugin ( wco , false , workerTsConfigPath ) ;
240
+ }
241
+
140
242
const { buildOptions } = wco ;
141
243
142
244
let pluginOptions : AngularCompilerPluginOptions = {
0 commit comments