Question regarding multi router in angular11

Viewed 72

I have a question here, I don't know have I follow the best practice of the angular even it is works now:

here is the structure of this nested component: pages

enter image description here

and here is my app-routing.module.ts file:

const routes: Routes = [
  { path: 'register', component: RegisterComponent },
  { path: 'home', component: HomeComponent },
  { path: 'login', component: LoginComponent },
  { path: 'welcome', component: WelcomeComponent, canActivate: [AuthGuard] },
  {
    path: 'admin',
    component: AdminComponent,
    canActivate: [AuthGuard],
    children: [{ path: 'team', component: TeamComponent }],
  },

  { path: '', redirectTo: 'home', pathMatch: 'full' },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
})
export class AppRoutingModule {}

So, team component is the sub component of Admin component, there is a navigation bar in Admin component and it will render the team component inside.

Code for Admin component:

<app-nav-admin></app-nav-admin>

<router-outlet></router-outlet>

Code for navigation bar href to team component HTML:

   <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav me-auto mb-2 mb-lg-0">
        <li class="nav-item">
          <a class="nav-link" href="admin/team">Team management</a>
        </li>
        <li class="nav-item">
          <a class="nav-link">Link</a>
        </li>
      </ul>
    </div>

and result after click on team link: enter image description here

as you can see in href value, I assigned ""admin/team"" to go to team component and it really works, but is this is the best practice?

Thanks guys!

2 Answers

You're getting there almost. However, now if on one page you need the FormsModule because you want to use the NgModelDirective in your template, you will be loading the FormsModule for each page in the AppModule, even when you don't need it. Best practice is to implement route-level code-splitting, eg. use one module per page.

You can use the following command to generate pages:

ng g module register --module account --route account

This will generate both a module and component that allows you to separate your dependencies. Full example:

cd app
ng g module pages --module app --route /
cd pages
ng g module account --module pages --route account
cd account
ng g module register --module account --route register
ng g module login --module account --route login
ng g module profile --module account --route profile

Make sure that

  • the PagesModule is not imported in the AppModule
  • the AccountModule is not imported in the PagesModule
  • the RegisterModule, LoginModule, and ProfileModule are not imported in the AccountModule

It also allows you to have a shared html banner or snippet whenever you're on any page related to, say account settings. In your case this would be in admin.componrnt.html:

<app-nav-admin></app-nav-admin>
<router-outlet></router-outlet>

You will notice that the size of your main.xxxxxx.js (main bundle) decreases drastically), so your app will load faster. However when navigating, the other modules needed for the other page aren't loaded yet, so you will experience a delay. To resolve this, you can use the preloadingstrategy: PreloadAllModules in the options of your RouterModule.forRoot() call (app-routing.module.ts)

Also note that the resulting AccountRoutingModule has the following routes:

const routes: Routes = [
  { path: 'login', loadChildren: () => import('./login/login.module').then(m => m.LoginModule) },
  { path: 'register', loadChildren: () => import('./register/register.module').then(m => m.RegisterModule) },
  { path: 'profile', loadChildren: () => import('./profile/profile.module').then(m => m.ProfileModule) },
];

The import('') instruction decouples your modules, while still allowing strong-type-checking. So the modules do not need to be imported in the AccountModule.

As a sidenote, you can you Lighthouse, which is built-in in Chrome, to evaluate your website. It will detect that you have an angular app, and one of the suggestions will be the use of route-level code-splitting. Since Lighthouse detects that the entire javascript application is loaded at once, including modules it doesn't need at that time. To use Lighthouse, in Chrome simply press F12 to open developer tools, and there will be a tab Lighthouse.

Your approach work, but I recommend use modules (https://angular.io/guide/feature-modules) for good implementation in your projects.

For example, you could have an Admin Module and this module would have its own router. In this way, you have more control of the routes and child components also you can implement lazy loading too.

Related