angular-cli: Lazy loading is not working together with 'import *' syntax

Please provide us with the following information:

OS?

Mac OSX El Capitan

Versions.

angular-cli: 1.0.0-beta.16 node: 5.7.1 os: darwin x64

Repro steps.

Was this an app that wasn’t created using the CLI? What change did you do on your code? etc. The app was not created using the CLI. When upgrading to Angular 2 I choose to use the CLI as serving and building tool

I have this route in my app.routing.ts:

const ROUTES: Routes = [
    { path: '', redirectTo: 'analyse', pathMatch: 'full' },
    { path: 'annotate', component: AnnotateComponent },
    { path: 'fraud', component: FraudComponent },
    { path: 'info',  loadChildren: 'app/info/info.module#InfoModule'  },
];```

the InfoModule should be loaded lazily when navigating to it's path. But even in de --prod build there's no seperate bundle. The InfoModule is still part of the main.bundle.js.

Note that I'm still importing the InfoModule in the app.module.ts otherwise the info route does not work at all.

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 11
  • Comments: 85 (20 by maintainers)

Commits related to this issue

Most upvoted comments

figured out the culprit; import * as moment from 'moment' anywhere in the eagerly-loaded module will prevent lazy loading, and instead loadChildren modules will be included in the main bundle. I suspect importing d3 and other libraries will have the same issue.

The work around is to define the library in angular-cli.json’ scripts definitions, and add a declare var moment: any in the typescript code, instead of an import.

However, workaround fails if other imported libraries has that import * as moment in its source code. For example, ng2-bootstrap’s datepicker module : /

Workaround to that workaround is to fork valor’s ng2-bootstrap datepicker…

You should not import InfoModule nowhere else. Only reference in routes’ loadChildren

Adding simply the below Fixed the issue…

"../node_modules/moment/moment.js" in angular-cli.json

But this should be a workaround… and not the actual Fix.

@VinayLeaf All you need to do is to avoid wildcard imports e.g.:

import * as moment from 'moment'

instead you need to include import into angular-cli.json e.g.:

"scripts": [
"../node_modules/moment/moment.js"
]

and then add typing for moment e.g.:

declare var moment: any;

And that’s pretty it. I hope that will help you 😃

PS. also you can try to import it as polyfill, but declaration of variable still should be added somewhere in types

Any progress with this issue @filipesilva? It has label “priority: 1 (urgent)” almost one month. It is blocking me to update my project to newest angular-cli version.

I did not yet investigate, but I made a repo that can reproduce this issue: https://github.com/aaronleeucla/angular-cli-lazy-load-bug-repro/blob/master/src/app/app-routing.module.ts

Running ng serve on this project, you can see that when either DatepickerModule is imported into NgModule or when moment() is used in the eagerly loaded MainPage component, lazy loading fails silently.

Not a fix for import * as breaking Lazy loading, but I have a workaround for those using angular2-moment.

I was previously using angular2-moment for the DateFormatPipe (for cross-browser formatting). That adds 50kb of code for one pipe and currently breaks Lazy-loading: screenshot 2017-01-21 17 23 07

Solution: switch to date-fns instead, it’s modern, modular, smaller and works with lazy-loading:

Site: https://date-fns.org/ Project: https://github.com/date-fns/date-fns Example pipe for formatting a date:

import { Pipe, PipeTransform } from '@angular/core';
import { format } from 'date-fns';

@Pipe({
  name: 'fnsDateFormat'
})
export class DateFormatPipe implements PipeTransform {
  transform(value: Date | string | number, ...args: any[]): any {
    if (!value) return '';
    return format(value, args[0]);
  }
}

And from switching, now it uses 27.8kb and I have lazy-loading again: screenshot 2017-01-21 17 39 04

Great work figuring out the cause @aaronleeucla! This definitely should not happen and is a bug.

I can confirm this behaviour too in CLI 25.5 - lazy loading and chunking work fine until I add any of these in a Feature module and then chunking stops chunking so to speak… import { Moment } from ‘moment’; import { MomentModule } from ‘angular2-moment’;

@Richard87 you should set root path in DashboardModule as path: ''. So it will be

RouterModule.forChild([{
  path: '',
  component: DashboardComponent,
  children: [