@@ -11,6 +11,7 @@ import {WebpackCompilerHost} from './compiler_host';
11
11
import { resolveEntryModuleFromMain } from './entry_resolver' ;
12
12
import { Tapable } from './webpack' ;
13
13
import { PathsPlugin } from './paths-plugin' ;
14
+ import { findLazyRoutes , LazyRouteMap } from './lazy_routes' ;
14
15
15
16
16
17
/**
@@ -39,7 +40,7 @@ export class AotPlugin implements Tapable {
39
40
private _rootFilePath : string [ ] ;
40
41
private _compilerHost : WebpackCompilerHost ;
41
42
private _resourceLoader : WebpackResourceLoader ;
42
- private _lazyRoutes : { [ route : string ] : string } ;
43
+ private _lazyRoutes : LazyRouteMap = Object . create ( null ) ;
43
44
private _tsConfigPath : string ;
44
45
private _entryModule : string ;
45
46
@@ -56,6 +57,8 @@ export class AotPlugin implements Tapable {
56
57
private _i18nFormat : string ;
57
58
private _locale : string ;
58
59
60
+ private _firstRun = true ;
61
+
59
62
constructor ( options : AotPluginOptions ) {
60
63
this . _setupOptions ( options ) ;
61
64
}
@@ -78,6 +81,7 @@ export class AotPlugin implements Tapable {
78
81
get i18nFile ( ) { return this . _i18nFile ; }
79
82
get i18nFormat ( ) { return this . _i18nFormat ; }
80
83
get locale ( ) { return this . _locale ; }
84
+ get firstRun ( ) { return this . _firstRun ; }
81
85
82
86
private _setupOptions ( options : AotPluginOptions ) {
83
87
// Fill in the missing options.
@@ -194,6 +198,31 @@ export class AotPlugin implements Tapable {
194
198
}
195
199
}
196
200
201
+ private _findLazyRoutesInAst ( ) : LazyRouteMap {
202
+ const result : LazyRouteMap = Object . create ( null ) ;
203
+ const changedFilePaths = this . _compilerHost . getChangedFilePaths ( ) ;
204
+ for ( const filePath of changedFilePaths ) {
205
+ const fileLazyRoutes = findLazyRoutes ( filePath , this . _program , this . _compilerHost ) ;
206
+ for ( const routeKey of Object . keys ( fileLazyRoutes ) ) {
207
+ const route = fileLazyRoutes [ routeKey ] ;
208
+ if ( routeKey in this . _lazyRoutes ) {
209
+ if ( route === null ) {
210
+ this . _lazyRoutes [ routeKey ] = null ;
211
+ } else if ( this . _lazyRoutes [ routeKey ] !== route ) {
212
+ this . _compilation . warnings . push (
213
+ new Error ( `Duplicated path in loadChildren detected during a rebuild. `
214
+ + `We will take the latest version detected and override it to save rebuild time. `
215
+ + `You should perform a full build to validate that your routes don't overlap.` )
216
+ ) ;
217
+ }
218
+ } else {
219
+ result [ routeKey ] = route ;
220
+ }
221
+ }
222
+ }
223
+ return result ;
224
+ }
225
+
197
226
// registration hook for webpack plugin
198
227
apply ( compiler : any ) {
199
228
this . _compiler = compiler ;
@@ -220,7 +249,15 @@ export class AotPlugin implements Tapable {
220
249
result . dependencies . forEach ( ( d : any ) => d . critical = false ) ;
221
250
result . resolveDependencies = ( p1 : any , p2 : any , p3 : any , p4 : RegExp , cb : any ) => {
222
251
const dependencies = Object . keys ( this . _lazyRoutes )
223
- . map ( ( key ) => new ContextElementDependency ( this . _lazyRoutes [ key ] , key ) ) ;
252
+ . map ( ( key ) => {
253
+ const value = this . _lazyRoutes [ key ] ;
254
+ if ( value !== null ) {
255
+ return new ContextElementDependency ( value , key ) ;
256
+ } else {
257
+ return null ;
258
+ }
259
+ } )
260
+ . filter ( x => ! ! x ) ;
224
261
cb ( null , dependencies ) ;
225
262
} ;
226
263
return callback ( null , result ) ;
@@ -314,18 +351,26 @@ export class AotPlugin implements Tapable {
314
351
this . _compilerHost . populateWebpackResolver ( this . _compiler . resolvers . normal ) ;
315
352
} )
316
353
. then ( ( ) => {
317
- // Process the lazy routes
318
- this . _lazyRoutes = { } ;
319
- const allLazyRoutes = __NGTOOLS_PRIVATE_API_2 . listLazyRoutes ( {
320
- program : this . _program ,
321
- host : this . _compilerHost ,
322
- angularCompilerOptions : this . _angularCompilerOptions ,
323
- entryModule : this . _entryModule
324
- } ) ;
325
- Object . keys ( allLazyRoutes )
354
+ // We need to run the `listLazyRoutes` the first time because it also navigates libraries
355
+ // and other things that we might miss using the findLazyRoutesInAst.
356
+ let discoveredLazyRoutes : LazyRouteMap = this . firstRun ?
357
+ __NGTOOLS_PRIVATE_API_2 . listLazyRoutes ( {
358
+ program : this . _program ,
359
+ host : this . _compilerHost ,
360
+ angularCompilerOptions : this . _angularCompilerOptions ,
361
+ entryModule : this . _entryModule
362
+ } )
363
+ : this . _findLazyRoutesInAst ( ) ;
364
+
365
+ // Process the lazy routes discovered.
366
+ Object . keys ( discoveredLazyRoutes )
326
367
. forEach ( k => {
327
- const lazyRoute = allLazyRoutes [ k ] ;
368
+ const lazyRoute = discoveredLazyRoutes [ k ] ;
328
369
k = k . split ( '#' ) [ 0 ] ;
370
+ if ( lazyRoute === null ) {
371
+ return ;
372
+ }
373
+
329
374
if ( this . skipCodeGeneration ) {
330
375
this . _lazyRoutes [ k ] = lazyRoute ;
331
376
} else {
@@ -334,7 +379,13 @@ export class AotPlugin implements Tapable {
334
379
}
335
380
} ) ;
336
381
} )
337
- . then ( ( ) => cb ( ) , ( err : any ) => {
382
+ . then ( ( ) => {
383
+ this . _compilerHost . resetChangedFileTracker ( ) ;
384
+
385
+ // Only turn this off for the first successful run.
386
+ this . _firstRun = false ;
387
+ cb ( ) ;
388
+ } , ( err : any ) => {
338
389
compilation . errors . push ( err ) ;
339
390
cb ( ) ;
340
391
} ) ;
0 commit comments