@@ -11,6 +11,7 @@ import {WebpackCompilerHost} from './compiler_host';
1111import { resolveEntryModuleFromMain } from './entry_resolver' ;
1212import { Tapable } from './webpack' ;
1313import { PathsPlugin } from './paths-plugin' ;
14+ import { findLazyRoutes , LazyRouteMap } from './lazy_routes' ;
1415
1516
1617/**
@@ -39,7 +40,7 @@ export class AotPlugin implements Tapable {
3940 private _rootFilePath : string [ ] ;
4041 private _compilerHost : WebpackCompilerHost ;
4142 private _resourceLoader : WebpackResourceLoader ;
42- private _lazyRoutes : { [ route : string ] : string } ;
43+ private _lazyRoutes : LazyRouteMap = Object . create ( null ) ;
4344 private _tsConfigPath : string ;
4445 private _entryModule : string ;
4546
@@ -56,6 +57,8 @@ export class AotPlugin implements Tapable {
5657 private _i18nFormat : string ;
5758 private _locale : string ;
5859
60+ private _firstRun = true ;
61+
5962 constructor ( options : AotPluginOptions ) {
6063 this . _setupOptions ( options ) ;
6164 }
@@ -78,6 +81,7 @@ export class AotPlugin implements Tapable {
7881 get i18nFile ( ) { return this . _i18nFile ; }
7982 get i18nFormat ( ) { return this . _i18nFormat ; }
8083 get locale ( ) { return this . _locale ; }
84+ get firstRun ( ) { return this . _firstRun ; }
8185
8286 private _setupOptions ( options : AotPluginOptions ) {
8387 // Fill in the missing options.
@@ -194,6 +198,31 @@ export class AotPlugin implements Tapable {
194198 }
195199 }
196200
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+
197226 // registration hook for webpack plugin
198227 apply ( compiler : any ) {
199228 this . _compiler = compiler ;
@@ -220,7 +249,15 @@ export class AotPlugin implements Tapable {
220249 result . dependencies . forEach ( ( d : any ) => d . critical = false ) ;
221250 result . resolveDependencies = ( p1 : any , p2 : any , p3 : any , p4 : RegExp , cb : any ) => {
222251 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 ) ;
224261 cb ( null , dependencies ) ;
225262 } ;
226263 return callback ( null , result ) ;
@@ -314,18 +351,26 @@ export class AotPlugin implements Tapable {
314351 this . _compilerHost . populateWebpackResolver ( this . _compiler . resolvers . normal ) ;
315352 } )
316353 . 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 )
326367 . forEach ( k => {
327- const lazyRoute = allLazyRoutes [ k ] ;
368+ const lazyRoute = discoveredLazyRoutes [ k ] ;
328369 k = k . split ( '#' ) [ 0 ] ;
370+ if ( lazyRoute === null ) {
371+ return ;
372+ }
373+
329374 if ( this . skipCodeGeneration ) {
330375 this . _lazyRoutes [ k ] = lazyRoute ;
331376 } else {
@@ -334,7 +379,13 @@ export class AotPlugin implements Tapable {
334379 }
335380 } ) ;
336381 } )
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 ) => {
338389 compilation . errors . push ( err ) ;
339390 cb ( ) ;
340391 } ) ;
0 commit comments