NgModule
@NgModule({
imports: [
CommonModule,
CustomMaterialModule,
...
],
exports: [
CommonModule,
CustomMaterialModule,
Components.AccountComponent,
Components.DateTimeComponent,
...
],
declarations: [
Components.AccountComponent,
Components.DateTimeComponent,
...
],
providers: []
})
export class SharedModule { }
})
Module types
- App module
- Core module
- Shared module
- Feature module
- Custom module
Disorganized AppModule
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule, Http } from '@angular/http';
import { RouterModule, RouterLink } from '@angular/router';
import { ReactiveFormsModule } from '@angular/forms';
import { MaterialModule, MdIconRegistry, MdSelectModule } from '@angular/material';
import { FlexLayoutModule } from '@angular/flex-layout';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { StoreModule } from '@ngrx/store';
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
import { EffectsModule } from '@ngrx/effects';
import { RouterStoreModule } from '@ngrx/router-store';
import { ContextMenuModule } from 'angular2-contextmenu';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { AppAlertService } from './services/app-alert.service';
import { AuthService } from './services/auth.service';
import { ExtendedHttpService } from './services/extended-http.service';
import { reducer } from './redux/reducers';
import { RoundingRuleEffects } from './redux/effects/rounding-rule';
import { SiteEffects } from './redux/effects/site';
import { DialogModule } from './components/dialogs/app-dialog.module';
import { NotFoundComponent } from './components/not-found/not-found.component';
import { DateTimeComponent } from './components/partials/date-time/date-time.component';
import { TimeService } from './services/time.service';
import { GreetingsComponent } from './components/partials/account/greetings/greetings.component';
import { LogoComponent } from './components/partials/logo/logo.component';
import { LoggedInGuard } from './guards/logged-in.guard';
import { PermissionGuard } from './guards/permission.guard';
import { LoginComponent } from './components/login/login.component';
import { AccountComponent } from './components/partials/account/account.component';
import { LoaderComponent } from './components/partials/loader/loader.component';
import { InsufficientPermissionsComponent } from './components/insufficient-permissions/insufficient-permissions.component';
import { PrettyPrintPipe } from './pipes/pretty-print.pipe';
import { SitePickerComponent } from './components/partials/site-picker/site-picker/site-picker.component';
import { RulesModule } from './components/rules/rules.module';
import { PowerbiModule } from './components/reports/powerbi/powerbi.module';
import { CustomReportsModule } from './components/reports/custom/custom-reports.module';
import { HomeModule } from './components/home/home.module';
import { LoaderService } from './services/loader.service';
@NgModule({
declarations: [
AppComponent,
NotFoundComponent,
DateTimeComponent,
GreetingsComponent,
LogoComponent,
LoginComponent,
AccountComponent,
LoaderComponent,
InsufficientPermissionsComponent,
PrettyPrintPipe,
SitePickerComponent,
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
AppRoutingModule,
ReactiveFormsModule,
MaterialModule,
FlexLayoutModule,
DialogModule,
ContextMenuModule,
BrowserAnimationsModule,
HomeModule,
CustomReportsModule,
PowerbiModule,
RulesModule,
StoreModule.provideStore(reducer),
RouterStoreModule.connectRouter(),
StoreDevtoolsModule.instrumentOnlyWithExtension(),
EffectsModule.run(RoundingRuleEffects),
EffectsModule.run(SiteEffects),
],
providers: [
MdIconRegistry,
MdSelectModule,
AppAlertService,
TimeService,
LoggedInGuard,
PermissionGuard,
RouterLink,
AuthService,
{ provide: Http, useClass: ExtendedHttpService },
LoaderService
],
bootstrap: [AppComponent]
})
export class AppModule {
constructor() {
}
}
})
110 Lines of code and can grow...
disorganized Folders Sturecture
Core, Feature, Shared, Custom
Organized AppModule
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { CoreModule } from './core/core.module';
import { SharedModule } from './shared/shared.module';
import { ComponentsModule } from './components';
import { AppRoutingModule } from './app-routing.module';
@NgModule({
declarations: [
AppComponent,
],
imports: [
AppRoutingModule,
ComponentsModule,
CoreModule,
SharedModule
],
bootstrap: [AppComponent]
})
export class AppModule {
constructor() { }
}
21 Lines of code
Style Guide #04-06
Lazy loading
- We are loading feature modules
- No references exposed from feature module
- Use `loadChildren` proerty with `text link` to your module
- Feature routing module + feature module
Lazy loading LoadChildren
import { MyComponent } from './components';
...
{
path: 'stuff',
component: MyComponent
}
{
path: 'stuff',
loadChildren: 'app/features/my-feature/my-feature.module#MyModule'
}
Lazy loading Routes
const routes: Routes = [
{
path: '',
children: [
{
path: '',
component: MyComponent
},
]
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class MyRoutingModule { }
Lazy loading Module
@NgModule({
imports: [
CommonModule,
PowerbiRoutingModule,
FormsModule,
NgxDatatableModule,
ReactiveFormsModule,
FormsModule,
HttpModule,
SharedHttpModule.forRoot(),
CustomMaterialModule
],
declarations: [
MyComponent,
]
})
export class MyModule { }
}
Module.ForRoot() pattern
@NgModule({
imports: [
CommonModule,
HttpModule
],
exports: [
CommonModule,
HttpModule
]
})
export class MyModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: MyModule,
providers: [
service1,
service2
]
};
}
}
Bafore vs After
Things to notice
import pickBy from 'lodash';
import * as moment from 'moment';
import { Observable } from 'rxjs';
import pickBy from 'lodash-es/pickBy';
import * as moment from 'moment-mini';
import { Observable } from 'rxjs/Observable';
Custom module
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import {
MdDialogModule,
MdToolbarModule
} from '@angular/material';
@NgModule({
imports: [
CommonModule,
MdDialogModule,
MdToolbarModule
],
exports: [
CommonModule,
MdDialogModule,
MdToolbarModule
]
})
export class CustomMaterialModule { }
Issue #4137
RxJS imports
rxjs-operators.ts
import 'rxjs/add/observable/throw';
import 'rxjs/add/observable/interval';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
Before
import 'rxjs/add/operator/map';
MyObservable$.map((cities: City[]) =>
new city.LoadSuccessAction(cities)
)
After
MyObservable$.map((cities: City[]) =>
new city.LoadSuccessAction(cities)
)
Lodash imports
lodash-functions.ts
import pickBy from 'lodash-es/pickBy';
import cloneDeep from 'lodash-es/cloneDeep';
export {
pickBy,
cloneDeep
}
Usage
import { pickBy } from './../../../core/lodash-functions';
...
return pickBy(item, function(value, key) { return !key.startsWith('$$'); }) as T;