0

I am using Angular "Lazy-loading feature modules" as an example: live demo

CustomersModule is a lazy loading module i create a test service in customer module.

const routes: Routes = [
  {
    path: 'customers',
    loadChildren: () => import('./customers/customers.module').then(m => m.CustomersModule)
  },
  {
    path: 'orders',
    loadChildren: () => import('./orders/orders.module').then(m => m.OrdersModule)
  },
  {
    path: '',
    redirectTo: '',
    pathMatch: 'full'
  }
];
import { Injectable } from '@angular/core';

@Injectable()
export class TestService {
  constructor() { }

  getHeroes() { return "HEROES"; }
}

in CustomersModule, add it to providers:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CustomersRoutingModule } from './customers-routing.module';
import { CustomersComponent } from './customers.component';
import {TestService} from "./test.service";

@NgModule({
  imports: [
    CommonModule,
    CustomersRoutingModule
  ],
  providers: [
    TestService
  ],
  declarations: [CustomersComponent]
})
export class CustomersModule { }

CustomersModule also has a CustomersComponent, by this way i can use TestService in it.

import { Component, OnInit } from '@angular/core';
import {TestService} from "./test.service";

@Component({
  selector: 'app-customers',
  templateUrl: './customers.component.html',
  styleUrls: ['./customers.component.css']
})
export class CustomersComponent implements OnInit {


   testService: TestService;

  constructor(test: TestService) {
    this.testService = test;
  }

  ngOnInit() {
  }

  test(){
    console.log(this.testService.getHeroes());
  }
}

but when i remove the TestService from providers array of CustomersModule and use providedIn in TestService:

import { Injectable } from '@angular/core';
import {CustomersModule} from "./customers.module";

@Injectable({
  providedIn: CustomersModule
})
export class TestService {
  constructor() { }

  getHeroes() { return "HEROES"; }
}

i got this error:

core.js:6228 ERROR Error: Uncaught (in promise): ReferenceError: Cannot access 'CustomersModule' before initialization
ReferenceError: Cannot access 'CustomersModule' before initialization
    at Module.CustomersModule (customers.component.ts:9)
    at Module../src/app/customers/test.service.ts (test.service.ts:5)
    at __webpack_require__ (bootstrap:84)
    at Module../src/app/customers/customers.component.ts (customers-customers-module.js:78)
    at __webpack_require__ (bootstrap:84)
    at Module../src/app/customers/customers-routing.module.ts (customers-customers-module.js:29)
    at __webpack_require__ (bootstrap:84)
    at Module../src/app/customers/customers.module.ts (customers.component.ts:9)
    at __webpack_require__ (bootstrap:84)
    at ZoneDelegate.invoke (zone-evergreen.js:364)
    at resolvePromise (zone-evergreen.js:798)
    at resolvePromise (zone-evergreen.js:750)
    at zone-evergreen.js:860
    at ZoneDelegate.invokeTask (zone-evergreen.js:399)
    at Object.onInvokeTask (core.js:41632)
    at ZoneDelegate.invokeTask (zone-evergreen.js:398)
    at Zone.runTask (zone-evergreen.js:167)
    at drainMicroTaskQueue (zone-evergreen.js:569)

I know there is circular dependecny here, for eagerly loaded modules it works and will enable tree-shaking. Does it mean in lazy loading modules only providers array can be used in NgModule?

are there guidelines/best practice for this?

Eddy Shan
  • 1
  • 1

3 Answers3

0

There is definitely circular dependency, that looks like this

CustomersComponent -> TestService -> CustomersModule -> CustomersComponent -> TestService

that's why you are getting this exception CustomersModule and TestService are injecting one another, so injecting it's in the provider array (instead of providedIn), will do the same thing, so undo your changes and leave TestService in providers array. Angular will optimize it the same way as it would do for providedIn attribute

onik
  • 1,404
  • 1
  • 10
  • 17
0

try like this.

@Injectable({
  providedIn: 'root'
})

Let me know if you still face any issue.

Piyush Jain
  • 1,527
  • 3
  • 11
  • 26
0

See this issue. The providedIn property is extremely confusing in this aspect.

Does it mean in lazy loading modules only providers array can be used in NgModule?

Yes, so, unfortunately, tree-shaking is out of the picture with lazy-loaded modules.