Angular-cli: Lazy load of modules don't work when using barrel file

Created on 4 Mar 2018  路  6Comments  路  Source: angular/angular-cli

This is a follow up of https://github.com/angular/angular/issues/22490

Versions

CLI 1.7.1

Repro steps

https://github.com/Lydon/lazy-loading

  • ng serve
  • Click on the login button
  • Check console error

Observed behavior

I am getting a error Error: Cannot find 'LoginModule' in './common/index' when having lazy routes with barrels.

After doing some debugging I tracked the issue to this function here which is creating the $$_lazy_route_resource file.
https://github.com/angular/angular-cli/blob/master/packages/@ngtools/webpack/src/angular_compiler_plugin.ts#L591

What I noticed was the while the call to ContextElementDependency was being done with the correct module names. Because of https://github.com/angular/angular-cli/blob/master/packages/@ngtools/webpack/src/angular_compiler_plugin.ts#L596 it only takes the path before the # as a module name, which in case you use a barrel file, you'll end up with the same module path for different import path.

If you take the below routes:

const routes: Routes = [
  {
    path: 'admin',
    loadChildren: './common/index#AdminModule'
  },
  {
    path: 'login',
    loadChildren: './common/index#LoginModule'
  },
  {
    path: 'register',
    loadChildren: './common/index#RegisterModule'
  }
];

The dependencies returned when calling ContextElementDependency would be:

[
 ContextElementDependency {
    module: null,
    request: '/Users/alan/lazy-loading/src/app/common/admin/admin.module.ts',
    userRequest: './common/index' },
  ContextElementDependency {
    module: null,
    request: '/Users/alan/lazy-loading/src/app/common/login/login.module.ts',
    userRequest: './common/index' },
  ContextElementDependency {
    module: null,
    request: '/Users/alan/lazy-loading/src/app/common/register/register.module.ts',
    userRequest: './common/index' } 
]

However it looks like webpack is deduping modules that share the same name when creating the $$_lazy_route_resource file and eventually the output map would be:

var map = {
    "./common/index": [
        "./src/app/common/register/register.module.ts",
        "register.module"
    ]
};

Desired behavior

No errors, and I can use lazy loading with barrel files.

Mention any other details that might be useful

1) I am not aware of the reason why it was decided to ignore the ngModule name part into from the module path that is passed to webpack. My Idea would be tp take it into consideration as well ie, not to take only the contents of the string before the #. That said, I know it would be that easy and need to make it backward compatible, as it effects changes in https://github.com/angular/angular/blob/c8a1a14b87e5907458e8e87021e47f9796cb3257/packages/core/src/linker/system_js_ng_module_factory_loader.ts as well.

2) Not sure if webpack provides as way to not dedupe or some other dependency mechanism to overcome this. And in all fairness, I am not sure if this is by webpack design.

//cc @TheLarkInn

devkibuild-angular low help wanted inconvenient triage #1 bufix faq

Most helpful comment

Yeah, I can confirm that this is still a problem with the latest Beta's for v6 of Angular CLI and Angular.

All 6 comments

Heya, yes this was a bug with how we processed lazy route paths. I looked around a bit and don't think this is sorted in 6.x

Yeah, I can confirm that this is still a problem with the latest Beta's for v6 of Angular CLI and Angular.

i can still confirm that it's a bug in angular/cli 7.1.4

The linked repository uses the old-style lazy modules (DeprecatedLoadChildren) in Angular v5:

  {
    path: 'admin',
    loadChildren: './common/index#AdminModule'
  },

The barrel files now work properly when using the new ES dynamic import() expression (LoadChildrenCallback), they even support aliased module classes (aka: renamed exports) and these dynamic imports also work nicely with TS path aliases.

I think that this story can be closed.

@SchnWalter, indeed this should no longer be a problem with dynamic imports.

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

_This action has been performed automatically by a bot._

Was this page helpful?
0 / 5 - 0 ratings