@@ -103,6 +103,11 @@ export interface AngularCompilerPluginOptions {
103103 nameLazyFiles ?: boolean ;
104104 logger ?: logging . Logger ;
105105 directTemplateLoading ?: boolean ;
106+ // When using the loadChildren string syntax, @ngtools/webpack must query @angular/compiler-cli
107+ // via a private API to know which lazy routes exist. This increases build and rebuild time.
108+ // When using Ivy, the string syntax is not supported at all. Thus we shouldn't attempt that.
109+ // This option is also used for when the compilation doesn't need this sort of processing at all.
110+ discoverLazyRoutes ?: boolean ;
106111
107112 // added to the list of lazy routes
108113 additionalLazyModules ?: { [ module : string ] : string } ;
@@ -134,6 +139,7 @@ export class AngularCompilerPlugin {
134139 private _compilerHost : WebpackCompilerHost & CompilerHost ;
135140 private _moduleResolutionCache : ts . ModuleResolutionCache ;
136141 private _resourceLoader ?: WebpackResourceLoader ;
142+ private _discoverLazyRoutes = true ;
137143 // Contains `moduleImportPath#exportName` => `fullModulePath`.
138144 private _lazyRoutes : LazyRouteMap = { } ;
139145 private _tsConfigPath : string ;
@@ -292,6 +298,26 @@ export class AngularCompilerPlugin {
292298 this . _platformTransformers = options . platformTransformers ;
293299 }
294300
301+ if ( options . discoverLazyRoutes !== undefined ) {
302+ this . _discoverLazyRoutes = options . discoverLazyRoutes ;
303+ }
304+
305+ if ( this . _discoverLazyRoutes === false && this . options . additionalLazyModuleResources
306+ && this . options . additionalLazyModuleResources . length > 0 ) {
307+ this . _warnings . push (
308+ new Error ( `Lazy route discovery is disabled but additional Lazy Module Resources were`
309+ + ` provided. These will be ignored.` ) ,
310+ ) ;
311+ }
312+
313+ if ( this . _discoverLazyRoutes === false && this . options . additionalLazyModules
314+ && Object . keys ( this . options . additionalLazyModules ) . length > 0 ) {
315+ this . _warnings . push (
316+ new Error ( `Lazy route discovery is disabled but additional lazy modules were provided.`
317+ + `These will be ignored.` ) ,
318+ ) ;
319+ }
320+
295321 // Default ContextElementDependency to the one we can import from here.
296322 // Failing to use the right ContextElementDependency will throw the error below:
297323 // "No module factory available for dependency type: ContextElementDependency"
@@ -411,7 +437,7 @@ export class AngularCompilerPlugin {
411437 this . _entryModule = resolveEntryModuleFromMain (
412438 this . _mainPath , this . _compilerHost , this . _getTsProgram ( ) as ts . Program ) ;
413439
414- if ( ! this . entryModule && ! this . _compilerOptions . enableIvy ) {
440+ if ( this . _discoverLazyRoutes && ! this . entryModule && ! this . _compilerOptions . enableIvy ) {
415441 this . _warnings . push ( 'Lazy routes discovery is not enabled. '
416442 + 'Because there is neither an entryModule nor a '
417443 + 'statically analyzable bootstrap code in the main file.' ,
@@ -697,64 +723,66 @@ export class AngularCompilerPlugin {
697723 ) ;
698724 } ) ;
699725
700- // Add lazy modules to the context module for @angular /core
701- compiler . hooks . contextModuleFactory . tap ( 'angular-compiler' , cmf => {
702- const angularCorePackagePath = require . resolve ( '@angular/core/package.json' ) ;
703-
704- // APFv6 does not have single FESM anymore. Instead of verifying if we're pointing to
705- // FESMs, we resolve the `@angular/core` path and verify that the path for the
706- // module starts with it.
707- // This may be slower but it will be compatible with both APF5, 6 and potential future
708- // versions (until the dynamic import appears outside of core I suppose).
709- // We resolve any symbolic links in order to get the real path that would be used in webpack.
710- const angularCoreResourceRoot = fs . realpathSync ( path . dirname ( angularCorePackagePath ) ) ;
711-
712- cmf . hooks . afterResolve . tapPromise ( 'angular-compiler' , async result => {
713- // Alter only existing request from Angular or one of the additional lazy module resources.
714- const isLazyModuleResource = ( resource : string ) =>
715- resource . startsWith ( angularCoreResourceRoot ) ||
716- ( this . options . additionalLazyModuleResources &&
717- this . options . additionalLazyModuleResources . includes ( resource ) ) ;
718-
719- if ( ! result || ! this . done || ! isLazyModuleResource ( result . resource ) ) {
720- return result ;
721- }
722-
723- return this . done . then (
724- ( ) => {
725- // This folder does not exist, but we need to give webpack a resource.
726- // TODO: check if we can't just leave it as is (angularCoreModuleDir).
727- result . resource = path . join ( this . _basePath , '$$_lazy_route_resource' ) ;
728- // tslint:disable-next-line:no-any
729- result . dependencies . forEach ( ( d : any ) => d . critical = false ) ;
730- // tslint:disable-next-line:no-any
731- result . resolveDependencies = ( _fs : any , options : any , callback : Callback ) => {
732- const dependencies = Object . keys ( this . _lazyRoutes )
733- . map ( ( key ) => {
734- const modulePath = this . _lazyRoutes [ key ] ;
735- if ( modulePath !== null ) {
736- const name = key . split ( '#' ) [ 0 ] ;
737-
738- return new this . _contextElementDependencyConstructor ( modulePath , name ) ;
739- } else {
740- return null ;
741- }
742- } )
743- . filter ( x => ! ! x ) ;
744-
745- if ( this . _options . nameLazyFiles ) {
746- options . chunkName = '[request]' ;
747- }
748-
749- callback ( null , dependencies ) ;
750- } ;
751-
726+ if ( this . _discoverLazyRoutes ) {
727+ // Add lazy modules to the context module for @angular /core
728+ compiler . hooks . contextModuleFactory . tap ( 'angular-compiler' , cmf => {
729+ const angularCorePackagePath = require . resolve ( '@angular/core/package.json' ) ;
730+
731+ // APFv6 does not have single FESM anymore. Instead of verifying if we're pointing to
732+ // FESMs, we resolve the `@angular/core` path and verify that the path for the
733+ // module starts with it.
734+ // This may be slower but it will be compatible with both APF5, 6 and potential future
735+ // versions (until the dynamic import appears outside of core I suppose).
736+ // We resolve symbolic links in order to get the real path that would be used in webpack.
737+ const angularCoreResourceRoot = fs . realpathSync ( path . dirname ( angularCorePackagePath ) ) ;
738+
739+ cmf . hooks . afterResolve . tapPromise ( 'angular-compiler' , async result => {
740+ // Alter only existing request from Angular or the additional lazy module resources.
741+ const isLazyModuleResource = ( resource : string ) =>
742+ resource . startsWith ( angularCoreResourceRoot ) ||
743+ ( this . options . additionalLazyModuleResources &&
744+ this . options . additionalLazyModuleResources . includes ( resource ) ) ;
745+
746+ if ( ! result || ! this . done || ! isLazyModuleResource ( result . resource ) ) {
752747 return result ;
753- } ,
754- ( ) => undefined ,
755- ) ;
748+ }
749+
750+ return this . done . then (
751+ ( ) => {
752+ // This folder does not exist, but we need to give webpack a resource.
753+ // TODO: check if we can't just leave it as is (angularCoreModuleDir).
754+ result . resource = path . join ( this . _basePath , '$$_lazy_route_resource' ) ;
755+ // tslint:disable-next-line:no-any
756+ result . dependencies . forEach ( ( d : any ) => d . critical = false ) ;
757+ // tslint:disable-next-line:no-any
758+ result . resolveDependencies = ( _fs : any , options : any , callback : Callback ) => {
759+ const dependencies = Object . keys ( this . _lazyRoutes )
760+ . map ( ( key ) => {
761+ const modulePath = this . _lazyRoutes [ key ] ;
762+ if ( modulePath !== null ) {
763+ const name = key . split ( '#' ) [ 0 ] ;
764+
765+ return new this . _contextElementDependencyConstructor ( modulePath , name ) ;
766+ } else {
767+ return null ;
768+ }
769+ } )
770+ . filter ( x => ! ! x ) ;
771+
772+ if ( this . _options . nameLazyFiles ) {
773+ options . chunkName = '[request]' ;
774+ }
775+
776+ callback ( null , dependencies ) ;
777+ } ;
778+
779+ return result ;
780+ } ,
781+ ( ) => undefined ,
782+ ) ;
783+ } ) ;
756784 } ) ;
757- } ) ;
785+ }
758786
759787 // Create and destroy forked type checker on watch mode.
760788 compiler . hooks . watchRun . tap ( 'angular-compiler' , ( ) => {
@@ -922,27 +950,29 @@ export class AngularCompilerPlugin {
922950 // Make a new program and load the Angular structure.
923951 await this . _createOrUpdateProgram ( ) ;
924952
925- // Try to find lazy routes if we have an entry module.
926- // We need to run the `listLazyRoutes` the first time because it also navigates libraries
927- // and other things that we might miss using the (faster) findLazyRoutesInAst.
928- // Lazy routes modules will be read with compilerHost and added to the changed files.
929- let lazyRouteMap : LazyRouteMap = { } ;
930- if ( ! this . _JitMode || this . _firstRun ) {
931- lazyRouteMap = this . _listLazyRoutesFromProgram ( ) ;
932- } else {
933- const changedTsFiles = this . _getChangedTsFiles ( ) ;
934- if ( changedTsFiles . length > 0 ) {
935- lazyRouteMap = this . _findLazyRoutesInAst ( changedTsFiles ) ;
953+ if ( this . _discoverLazyRoutes ) {
954+ // Try to find lazy routes if we have an entry module.
955+ // We need to run the `listLazyRoutes` the first time because it also navigates libraries
956+ // and other things that we might miss using the (faster) findLazyRoutesInAst.
957+ // Lazy routes modules will be read with compilerHost and added to the changed files.
958+ let lazyRouteMap : LazyRouteMap = { } ;
959+ if ( ! this . _JitMode || this . _firstRun ) {
960+ lazyRouteMap = this . _listLazyRoutesFromProgram ( ) ;
961+ } else {
962+ const changedTsFiles = this . _getChangedTsFiles ( ) ;
963+ if ( changedTsFiles . length > 0 ) {
964+ lazyRouteMap = this . _findLazyRoutesInAst ( changedTsFiles ) ;
965+ }
936966 }
937- }
938967
939- // Find lazy routes
940- lazyRouteMap = {
941- ...lazyRouteMap ,
942- ...this . _options . additionalLazyModules ,
943- } ;
968+ // Find lazy routes
969+ lazyRouteMap = {
970+ ...lazyRouteMap ,
971+ ...this . _options . additionalLazyModules ,
972+ } ;
944973
945- this . _processLazyRoutes ( lazyRouteMap ) ;
974+ this . _processLazyRoutes ( lazyRouteMap ) ;
975+ }
946976
947977 // Emit files.
948978 time ( 'AngularCompilerPlugin._update._emit' ) ;
0 commit comments