Skip to content

Creating ROUTES with custom factory function ends up with "Cannot read property 'loadChildren' of undefined" error #9913

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
jtomaszewski opened this issue Mar 9, 2018 · 5 comments

Comments

@jtomaszewski
Copy link

jtomaszewski commented Mar 9, 2018

Versions

node 6.11.5
npm 5.6.0
angular 5.2.8
@ngtools/webpack 1.10.2

Repro steps

We have a custom webpack setup that uses @ngtools/webpack . Everything has been working good for us so far, in both JiT and AoT. Right now we are trying to setup lazy routes.

We wanted to implement them using the standard way (loadChildren: '../features/dashboard/dashboard.module#DashboardFeatureModule'), but it just didn't work. (We tried and checked everything.) Anyways, it doesn't matter, because loadChildren can accept a function returning a promise with ngModule. So we decided to load the module ourselves.

Example:

import { NgModule, NgModuleFactory, Compiler } from '@angular/core';
import { Routes, RouterModule, ROUTES } from '@angular/router';

export function MainRoutingLazyRoutesFactory(compiler: Compiler): Routes {
  return [
    {
      path: 'dashboard',
      loadChildren: () => {
        return <any>System.import('../features/dashboard/dashboard.module')
          .then(({ DashboardFeatureModule }) => DashboardFeatureModule)
          .then(ngModule => {
            if (ngModule instanceof NgModuleFactory) {
              return ngModule;
            } else {
              return compiler.compileModuleAsync(ngModule);
            }
          });
      },
    },
  ];
}

@NgModule({
  imports: [RouterModule],
  exports: [RouterModule],
  providers: [
    {
      provide: ROUTES,
      multi: true,
      deps: [Compiler],
      useFactory: MainRoutingLazyRoutesFactory,
    },
  ],
})
export class MainRoutingModule {}

Observed behavior

It fails with the following error during the first compilation in JiT and in any compilation in AoT:

ERROR in Cannot read property 'loadChildren' of undefined
webpack: Failed to compile.

(It leaves no stacktrace).

In JiT with webpack-dev-server, if you trigger a recompilation (by changing any file), it compiles correctly since the 2nd compilation and on every following one.

Seems like angular's compiler has some trouble while trying to parse our factory function. Should it parse it at all? I think we don't need the compiler to parse it all. Do you know any workaround, so we can fix the error, so the compiler parses it correctly or just doesn't try to parse it at all?

Desired behavior

Defining routes with a custom FactoryProvider should just work.

It lets you to easily implement lazy loaded modules with a custom way.


Additional note

If we downgrade to angular 5.2.5 and ngtools/webpack 1.10.0, then it behaves in the same way, but the error includes a stacktrace as well:

ERROR in TypeError: Cannot read property 'loadChildren' of undefined
    at _collectLoadChildren (/Users/jtomaszewski/src/recruitee/rails/admin_app/node_modules/@angular/compiler/bundles/compiler.umd.js:29034:20)
    at listLazyRoutes (/Users/jtomaszewski/src/recruitee/rails/admin_app/node_modules/@angular/compiler/bundles/compiler.umd.js:29009:49)
    at AotCompiler.listLazyRoutes (/Users/jtomaszewski/src/recruitee/rails/admin_app/node_modules/@angular/compiler/bundles/compiler.umd.js:31150:51)
    at AngularCompilerProgram.listLazyRoutes (/Users/jtomaszewski/src/recruitee/rails/admin_app/node_modules/@angular/compiler-cli/src/transformers/program.js:156:30)
    at AngularCompilerPlugin._listLazyRoutesFromProgram (/Users/jtomaszewski/src/recruitee/rails/admin_app/node_modules/@ngtools/webpack/src/angular_compiler_plugin.js:304:38)
    at Promise.resolve.then.then (/Users/jtomaszewski/src/recruitee/rails/admin_app/node_modules/@ngtools/webpack/src/angular_compiler_plugin.js:583:50)
    at process._tickCallback (internal/process/next_tick.js:109:7)
webpack: Failed to compile.
@jtomaszewski
Copy link
Author

jtomaszewski commented Mar 9, 2018

OK, I've followed the stack trace and think I've found what causes the bug.

I think it's because of this code in the angular/compiler's source:

function listLazyRoutes(moduleMeta, reflector) {
    var /** @type {?} */ allLazyRoutes = [];
    for (var _i = 0, _a = moduleMeta.transitiveModule.providers; _i < _a.length; _i++) {
        var _b = _a[_i], provider = _b.provider, module = _b.module;
        if (tokenReference(provider.token) === reflector.ROUTES) {
            var /** @type {?} */ loadChildren = _collectLoadChildren(provider.useValue);
            for (var _c = 0, loadChildren_1 = loadChildren; _c < loadChildren_1.length; _c++) {
                var route = loadChildren_1[_c];
                allLazyRoutes.push(parseLazyRoute(route, reflector, module.reference));
            }
        }
    }
    return allLazyRoutes;
}

According to the stacktrace, it fails on _collectLoadChildren(provider.useValue);.

Obviously, this provider has no useValue. IMHO we should skip parsing it, if it doesn't have such a property.

@clydin
Copy link
Member

clydin commented Mar 9, 2018

As this appears to be a defect in the Angular code itself, can you please open an issue here with a summary of your findings. And please reference this issue as well.
Also, thank you for spending the time to conduct the research into this issue.

@Brocco
Copy link
Contributor

Brocco commented Mar 9, 2018

I agree that this appears to be an issue with Angular itself and not the CLI, so I am closing this issue.

@mjamin
Copy link

mjamin commented Jul 11, 2018

Related to #9343

@angular-automatic-lock-bot
Copy link

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.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 8, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants