# Rutas

## Rutas

Las rutas sirven para dividir y abstraer mejor por rutas de dominio la aplicación.

Al generar la app puedes elegir que se agreguen los archivos para el *routing* de una vez, y queda de la siguente manera:

```typescript
// app-routing.module.ts
const routes: Routes = [
  {
    path: '',
    redirectTo: 'home', // sin slash, de lo contrario va a la ruta principal
    pathMatch: 'full'
  },
  {
    path: 'home',
    component: HomeComponent
  },
  {
    path: 'products',
    component: ProductsComponent
  },
  {
    path: 'product/:productId',
    component: ProductDetailComponent
  },
  {
    path: '**',
    component: NotFoundComponent
  }
];

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

```typescript
// app.module.ts
import { AppRoutingModule } from './app-routing.module';
@NgModule({
  // ..
  imports: [
    AppRoutingModule
  ],
})
export class AppModule { }
```

Observa la primera regla que tiene el `path` vacío y un `redirectTo` para redireccionar al componente *home* cuando no se ingresa ninguna ruta. Utiliza también la opción `pathMatch` para asegurar que la ruta sea exacta. Podría quedar solamente `path: '',` y sin otra regla con redirect hacía *home* y funcionaria igual.

También para las páginas no encontradas se usa `path: '**'` .Es muy importante que esta regla para manejo de rutas no definidas se encuentre ubicado en el último lugar del array. Angular analiza las rutas en el mismo orden en que las defines. Si esta regla se encuentra en primer lugar, puede anular las demás y darte algunos problemas.

Finalmente, tienes que importar la directiva `<router-outlet>` en el componente raíz de tu aplicación.

```html
<!-- app.component.html -->
<router-outlet></router-outlet>
```

### Redirecciones sin recargar `routerLink`

Para poder movernos entre rutas sin recargar nuestra página debemos agregar a nuestras anclas ‘`<a>`’ la directiva **`routerLink`** envés del atributo **`href`** para que Angular determine que no haga una recarga de la página.

```markup
<div><a routerLink="/home">Home</a></div>
<!-- Antes <a href="/home">Home</a> -->
```

### Ancla activa `routerLinkActive`

Puedes definir una clase para cuando una ruta coincida con el routerLink al agregar la directiva `routerLinkActive.`

```html
<a routerLink="/home" routerLinkActive="active">Home</a>
```

### RouterLink con parametros

Podemos hacer uso de un arreglo y encerrar routerLink como si fuera un **property binding**

```markup
<a [routerLink]="['/products/', product.id]">Ver detalle</a>
```

O también utilizar el **string interpolation**

```markup
<a routerLink="/products/{{product.id}}">Ir al producto</a>
```

### Capturando parámetros de URL

Los parámetros se crean así en el archivo routing:

```typescript
// app-routing.module.ts
const routes: Routes = [
...
  {
    path: 'product/:productId',
    component: ProductDetailComponent
  },
...
```

Observa que ambas rutas apuntan al mismo componente, eso está bien. La diferencia estará en que la segunda ruta posee `:productId` y podrás capturar el parámetro utilizando ese mismo nombre.

### **Inyección de servicios necesarios**

En el componente correspondiente, inyecta el servicio **ActivatedRoute** y también importa **Params** para tipar tus datos y manipularlos más fácilmente. Ambos imports provenientes de `@angular/router`.

```javascript
import { ActivatedRoute, Params } from '@angular/router';

@Component({
  selector: 'app-catalogo',
  templateUrl: './catalogo.component.html',
  styleUrls: ['./catalogo.component.scss']
})
export class CatalogoComponent {
  constructor(private route: ActivatedRoute) { }
}
```

### Captura de parámetros síncronos

El mejor lugar para capturar parámetros de URL, sean síncronos o no, es utilizando los hooks de ciclo de vida de Angular, más concretamente `ngOnInit()`.

```typescript
ngOnInit(): void {
  const categoryId = this.route.snapshot.paramMap.get('productId');
  console.log(categoryId);
}
```

`this.route.snapshot.params`: Esta propiedad es una instantánea (snapshot) de los parámetros de la ruta en un momento determinado. Esto significa que si se accede a esta propiedad en un momento en particular, se obtendrán los valores de los parámetros de la ruta en ese momento. Si los parámetros cambian posteriormente, esta propiedad no se actualizará.

`snapshot.paramMap` también proporciona algunas funciones útiles para trabajar con los parámetros de la ruta, como por ejemplo:

* `get()`: Devuelve el valor de un parámetro especificado por su clave.
* `getAll()`: Devuelve todos los valores de un parámetro especificado por su clave.
* `has()`: Comprueba si un parámetro está presente en la ruta.
* `keys()`: Devuelve una lista de todas las claves de los parámetros de la ruta.

Por otro lado, `snapshot.params` simplemente proporciona un objeto con pares clave-valor y no tiene funciones adicionales para trabajar con los parámetros.

### Captura de parámetros asíncronos

Una URL puede cambiar y a veces es conveniente estar escuchando de forma activa los cambios en la misma. Para que los Observables nos ayuden a estar atentos a estos cambios, Angular también nos permite suscribirnos a los cambios en los parámetros de URL de la siguiente manera.

```typescript
ngOnInit(): void {
  this.route.paramMap
    .subscribe((params: Params) => {
      const productId = params.get('productId');
      console.log(productId);
    });
}
```

### Query Params

Los parámetros de ruta, por ejemplo `/catalogo/:categoryId`, son obligatorios. Sin el ID la ruta no funcionaría. Por otro lado, existen los parámetros de consulta que los reconocerás seguidos de un `?` y separados por un `&`, por ejemplo `/catalogo?limit=10&offset=0`.

#### 1. Creando rutas con parámetros

{% code overflow="wrap" %}

```html
<a routerLink="/catalogo" [queryParams]="{ category: 'electronica' }" routerLinkActive="active">Electrónica</a>
```

{% endcode %}

La directiva queryParams recibe un objeto y creará la ruta `/catalogo?category=electronica`

#### 2. Capturar parámetros en las rutas

Para capturar estos datos en el componente, es aconsejable realizarlo en el hook de ciclo de vida `ngOnInit()`.

Suscribiéndote a **queryParams**, podrás capturar y hacer uso de esta información.

```typescript
// modules/website/component/catalogo/catalogo.component.ts
import { ActivatedRoute, Params } from '@angular/router';

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

  constructor(private route: ActivatedRoute) { }

  ngOnInit(): void {
    this.route.queryParams
      .subscribe((params: Params) => {
        console.log(params.category);
      });
  }
}
```

Con un *punto* se puede hacer refencia a la ruta actual.

```html
<a routerLink="." [queryParams]="{ category: 'electronica' }">Electrónica</a>
```

## Optimización de tiempo y recursos

Para reducir el peso de las aplicaciones, aparece el concepto de *Lazy Loading* y el *CodeSplitting* que plantean la división del código fuente Javascript en pequeños módulos y solo cargar aquellos que el usuario necesite, cuando realmente los necesite.

### Code Splitting

Es la técnica que permite dividir el código y sus recursos en varias partes *(chunks)* que se pueden descargar en demanda y no solo en un solo archivo como se hace tradicionalmente, mejorando la velocidad de carga de las páginas.

<figure><img src="https://624742151-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFRKN8coRWwuuSr24p99X%2Fuploads%2FmpSz28pra50VuzpuqdUS%2Fimage.png?alt=media&#x26;token=db1f94e8-248d-4c8c-be1f-49f4154362d3" alt=""><figcaption></figcaption></figure>

### Lazy loading

El **lazy loading** en Angular es una técnica que permite cargar módulos de la aplicación de forma **diferida**, es decir, solo cuando son necesarios (por ejemplo, cuando un usuario navega a una ruta específica). Esto mejora el **rendimiento inicial** de la aplicación al reducir el tamaño del bundle cargado inicialmente.

#### **¿Por qué usar lazy loading?**

1. **Mejor tiempo de carga inicial**: Solo se carga el módulo principal al inicio.
2. **Optimización del rendimiento**: Los módulos adicionales se cargan bajo demanda.
3. **División del código (Code splitting)**: Permite dividir la aplicación en bundles más pequeños y manejables.

***

#### **Cómo implementar lazy loading**

1. **Estructura básica de la aplicación**\
   Supongamos que tienes una aplicación con dos módulos:
   * `AppModule` (módulo principal).
   * `FeatureModule` (módulo con funcionalidad específica).
2. **Crear un módulo para cargar de manera diferida**:\
   Genera un módulo y un componente:

   ```bash
   ng generate module feature --route feature --module app.module
   ```

   Esto genera automáticamente:

   * Un módulo llamado `FeatureModule`.
   * Un componente principal para ese módulo.
   * Configuración de lazy loading en el archivo de rutas.
3. **Configurar las rutas en `AppRoutingModule`**: Asegúrate de usar la propiedad `loadChildren` para cargar el módulo diferido:

   ```typescript
   import { NgModule } from '@angular/core';
   import { RouterModule, Routes } from '@angular/router';

   const routes: Routes = [
     { path: '', redirectTo: 'home', pathMatch: 'full' },
     { path: 'feature', loadChildren: () => import('./feature/feature.module').then(m => m.FeatureModule) },
   ];

   @NgModule({
     imports: [RouterModule.forRoot(routes)],
     exports: [RouterModule]
   })
   export class AppRoutingModule {}
   ```
4. **Configurar el módulo diferido (`FeatureModule`)**:\
   Define las rutas del módulo en su propio archivo de rutas:

   ```typescript
   import { NgModule } from '@angular/core';
   import { RouterModule, Routes } from '@angular/router';
   import { FeatureComponent } from './feature.component';

   const routes: Routes = [
     { path: '', component: FeatureComponent },
   ];

   @NgModule({
     imports: [RouterModule.forChild(routes)],
     exports: [RouterModule]
   })
   export class FeatureRoutingModule {}
   ```

   Luego importa `FeatureRoutingModule` en el `FeatureModule`:

   ```typescript
   typescriptCopy codeimport { NgModule } from '@angular/core';
   import { CommonModule } from '@angular/common';
   import { FeatureComponent } from './feature.component';
   import { FeatureRoutingModule } from './feature-routing.module';

   @NgModule({
     declarations: [FeatureComponent],
     imports: [CommonModule, FeatureRoutingModule],
   })
   export class FeatureModule {}
   ```

***

#### **Ventajas del lazy loading**

* Reduce el tiempo de carga inicial de la aplicación.
* Optimiza la experiencia del usuario, especialmente en aplicaciones grandes.
* Divide el código en módulos independientes, facilitando el mantenimiento.

#### **Nota**

Asegúrate de usar **Angular Router** para gestionar las rutas, ya que es el mecanismo principal para implementar lazy loading.

### **Modulos**

Un módulo encapsula varios elementos de una aplicación. Por lo general se modulariza cada grupo de componentes u otros elementos relacionados de nuestra aplicación.

Angular logra esto utilizando con `@NgModule`, cada módulo es como una isla que agrupa como se mencionó antes ciertas características en específico.

En otras palabras, no se pueden tener módulos que sirvan para toda la aplicación, cada vez que quieras trabajar con algún componente o característica en algún modulo en particular deberás importarlo, un ejemplo sería cuando usamos el módulo de `ReactiveFormsModule.`

### Cuáles son los módulos en Angular

Por defecto, Angular posee un solo módulo en el archivo `app.module.ts`. Todos tus componentes, servicios, pipe, etc. se importan aquí. Utiliza un decorador llamado `@ngModule()` con un aspecto similar al siguiente:

```javascript
// app.module.ts
@NgModule({
  imports: [],         // Imports de otros módulos.
  declarations: [],    // Imports de los componentes del módulo.
  exports: [],         // Exports de componentes u otros para ser utilizados en otros módulos.
  providers: [],       // Inyección de servicios.
  bootstrap: []        // Import del componente principal de la aplicación.
})
export class AppModule { }
```

Un módulo en Angular se define utilizando el decorador `@NgModule`, que recibe un objeto de metadatos con las siguientes propiedades principales:

1. **Declarations**: Esta propiedad contiene un arreglo de componentes, directivas y pipes que pertenecen a este módulo.
2. **Imports**: Aquí se especifican otros módulos cuyos componentes, directivas y pipes son necesarios en este módulo.
3. **Exports**: Define los componentes, directivas y pipes que pueden ser utilizados por otros módulos que importen este módulo.
4. **Providers**: Proporciona los servicios que deben ser disponibles de forma global o para el ámbito de este módulo.
5. **Bootstrap**: Especifica el componente raíz que Angular debe iniciar para arrancar la aplicación (principalmente en el módulo raíz `AppModule`).

Al modularizar una aplicación, cada módulo tendrá sus componentes exclusivos, servicios o los archivos que fuesen a necesitar.

### Tipos de Módulos en Angular

Podemos identificar varios tipos de módulos.

* **Root Module**: Módulo por defecto de Angular que inicia toda la aplicación (*App Module*).
* **Core Module**: Son servicios que pueden ser usados en diferentes módulos y componentes, recordar que los servicios se inyectan con `provideIn : ‘root’` y se puede usar en cualquier parte de la aplicación (Globales).
* **Routing Module**: Son módulos especiales para la definición de rutas.
* **Feature Domain Module**: Son los módulos propios de tu aplicación.
* **Shared Module**: Posee servicios o componentes compartidos por toda la aplicación, Por ejemplo, componentes *pipes* y directivas que se quieran usar en toda la aplicación.

## Vistas Anidadas

Trabajar con Angular en una aplicación **modularizada** da la posibilidad de que, cada módulo, tenga a su vez N cantidad de páginas hijas.

La técnica de vistas anidadas, nos sirve para incluir ciertos componentes a otros componentes que se especifiquen, un ejemplo sería que solo las rutas que utilicen el componente *Layout* tendrian incorporado el componente *Header*

Veámos un ejemplo.&#x20;

#### 1. Crear módulos necesarios

Podríamos decir que cada **grupo de rutas** podría ser un módulo, entonces creamos el modulo de *products*.

Suponiendo que tenemos una estructura como esta:

<figure><img src="https://624742151-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFRKN8coRWwuuSr24p99X%2Fuploads%2FyKRLOZEvYjj4QeVLA01a%2Fimage.png?alt=media&#x26;token=0fa9af3f-5c3c-4a13-bb89-4d6511d7d239" alt=""><figcaption></figcaption></figure>

Crearemos un modulo para la seccion de *website*

`ng generate module pages/website --routing`

#### 2. Preparación del routing

A continuación, prepara tu `app-routing.module.ts` para *Lazy Loading* y *CodeSplitting* importando los módulos de la siguiente manera:

```javascript
// app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { NotFoundComponent } from './pages/website/not-found/not-found.component';

const routes: Routes = [
  {
    path: '',
    loadChildren: () => import('./pages/website/website.module').then(m => m.WebsiteModule)
  },
  {
    path: '**',
    component: NotFoundComponent
  }
];

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

Observa que, a excepción del componente *NotFound*, solo estamos importando los módulos de una manera especial. Con `loadChildren`, cada módulo será enviado bajo demanda, ya que ahora se cargan de manera asíncrona.

#### 3. Renderizar módulos

El componente principal de tu aplicación será el encargado de renderizar cada módulo. Para esto, asegúrate de que solo posea el `<router-outlet>`, porque es todo lo que necesitas para lograrlo.

```javascript
// app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: '<router-outlet></router-outlet>',
  styleUrls: ['./app.component.scss']
})
export class AppComponent { }
```

Incluso puedes borrar el archivo app.components.html y colocar el `<router-outlet>` dentro de la propiedad `template` en el decorador `@Component()` para simplificar tu código.

#### 4. Componentes base

Creamos un componente *Layout*

*`ng g c components/layout`*

En el layout del módulo website, tiene su propio `<router-outlet>` además del componente para la barra de navegación.

```html
<app-nav></app-nav>
<router-outlet></router-outlet>
```

Este componente de barra de navegacion no va a aparecer en otras rutas si no se especifica, por ejempo en la ruta con el componente de *NotFound* no deberá aparece&#x72;*.*

#### 5. Routing de cada módulo

Finalmente, cada `<router-outlet>` de cada módulo renderizará los componentes que posea dichos módulos. Para esto, prepara el routing de cada módulo de la siguiente manera.

```javascript
// pages/website/website-routing.module.ts
const routes: Routes = [
  {
    path: '',
    component: LayoutComponent,
    children: [
      {
        path: '',
        redirectTo: 'home', // sin slash, de lo contrario va al rote principal
        pathMatch: 'full'
      },
      {
        path: 'home',
        component: HomeComponent
      },
      {
        path: 'products',
        component: ProductsComponent
      },
      {
        path: 'product/:productId',
        component: ProductDetailComponent
      },
    ]
  }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class WebsiteRoutingModule { }
```

Presta atención a la propiedad `children` que construye las nuevas reglas para las rutas.

De esta manera, puedes tener un `<router-outlet>` dentro de otro `<router-outlet>` para renderizar páginas hijas de cada módulo y tener un layout personalizado por nada uno de ellos. Además de estar optimizado el rendimiento de tu aplicación gracias **al&#x20;*****Lazy Loading*****&#x20;y&#x20;*****CodeSplitting*****.**

Podemos ver que la correr nuestra aplicación se genera aparte un archivo para el modulo de *website*

<figure><img src="https://624742151-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFRKN8coRWwuuSr24p99X%2Fuploads%2FeY4ZaaYu0gsURAiLufKk%2Fimage.png?alt=media&#x26;token=3b4695e1-a11f-4108-aae4-2b248ec3b26d" alt=""><figcaption></figcaption></figure>

## **SharedModule**

Un módulo compartido donde guardarás los componentes, pipes, directivas o servicios que dos o más de tus otros módulos necesitarán y los puedes incluir en tus otros modulos.

**Nota:** Un componente solo puede pertenecer a un módulo, no a dos.

## &#x20;All Modules y Custom Strategy

Al haber activado la técnica de *Lazy Loading*, puedes **personalizar el envío de estos módulos** al cliente con diferentes estrategias.

### Precarga de módulos bajo demanda

Por defecto, la aplicación enviará al cliente solo el módulo que necesita. Si ingresas al módulo website, solo se cargará su respectivo archivo JS.

Si el usuario solicita otro módulo, este se cargará solo cuando sea necesario.

Esto puede causarte problemas, ya que si el módulo solicitado es algo pesado o la conexión es lenta, tardará varios segundos en estar listo y no será buena la experiencia de usuario.

### Precarga de todos los módulos

Puedes decirle a tu aplicación que, por defecto, precargue todos los módulos con la siguiente configuración:

```typescript
// app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes, PreloadAllModules } from '@angular/router';

const routes: Routes = [
...

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

Importando **PreloadAllModules** desde `@angular/router`, lo pasas como parámetro al `import` en el decorador `@NgModule()`. El browser va a descargar primero los archivos base, es decir, los que tienen que ver con la carga inicial y luego que este libre el browser comenzará a precargar los módulos restantes.

* Es ideal para aplicaciones que no sean muy grandes o no ocupen muchos módulos.
* En el caso de tener muchos módulos es mejor usar una estrategia personalizada para evitar sobrecargar el hilo principal. De esta forma se establece que módulos se van a precargar.

### Estrategia personalizada de precarga

Precargar todos los módulos a la vez, puede ser contra producente. Imagina que tu aplicación posea 50 o 100 módulos. Sería lo mismo que tener todo en un mismo archivo `main.js`.

Para solucionar esto, puedes personalizar la estrategia de descarga de módulos indicando qué módulos si se deben precargar y cuáles no.

#### 1. Agrega metadata a cada ruta

Agrégale a cada regla en el routing de tu aplicación, metadata para indicarle a cada módulo si debe ser precargado, o no.

```javascript
// app-routing.module.ts
const routes: Routes = [
  {
    path: 'cms',
    loadChildren: () =>
      import('./pages/cms/cms.module').then((m) => m.CmsModule),
      data: { preload: true },
  },
  {
    path: '',
    loadChildren: () =>
      import('./pages/website/website.module').then((m) => m.WebsiteModule),
  },
  {
    path: '**',
    component: NotFoundComponent,
  },
];
```

Con la propiedad data: `{ preload: true }`, le indicas al servicio **CustomPreloadingStrategy** si el módulo debe ser precargado cuando el browser halla descargado ya todos los archivos base.

#### 2. Crea un servicio con estrategia personalizada

Crea un servicio al cual llamaremos **CustomPreloadingStrategy** con la siguiente lógica.

```javascript
// shared/services/custom-preloading-strategy.service.ts
import { Injectable } from '@angular/core';
import { Route, PreloadingStrategy } from '@angular/router';
import { Observable, of } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class CustomPreloadingStrategyService implements PreloadingStrategy {

  preload(route: Route, load: () => Observable<any>): Observable<any> {
    if (route.data && route.data.preload)
      return load();
    else
      return of(null);
  }

}
```

El servicio implementa **PreloadingStrategy** y sobreescribiendo el método `preload()`, hace uso de la metadata para desarrollar tu propia lógica de renderizado de módulos.

#### 3. Importa tu estrategia

Finalmente, importa tu estrategia personalizada en el routing.

```javascript
// app-routing.module.ts
import { CustomPreloadingStrategyService } from '../shared/services/custom-preloading-strategy.service';
// ...
@NgModule({
  imports: [RouterModule.forRoot(routes, {
    preloadingStrategy: CustomPreloadingStrategyService,
  })],
  exports: [RouterModule]
})
export class AppRoutingModule { }
```

De esta manera, ya puedes personalizar qué módulos serán enviados al cliente y cuáles no, mejorando así el rendimiento de tu aplicación.

## Guardianes

Hay veces que queremos que determinadas áreas de nuestra aplicación web estén protegidas y solo puedan ser accedidas si el usuario ésta logueado por ejemplo, o incluso que solo puedan ser accedidas por determinados tipos de usuarios.

* **CanLoad**: Sirve para evitar que la aplicación cargue los módulos *Lazy* si el usuario no está autorizado a hacerlo.
* **CanDeactivate**: Mira si el usuario puede salir de una página, es decir, podemos hacer que aparezca un mensaje, por ejemplo, de confirmación, si el usuario tiene cambios sin guardar.
* **CanActivateChild**: Mira si el usuario puede acceder a las páginas hijas de una determinada ruta.
* **CanActivate**: Mira si el usuario puede acceder a una página determinada.

### 1. Creando el primer guard

Al utilizar este comando, nos hará una pregunta sobre qué interfaz quieres que implemente por defecto:

```
ng g g admin
```

<figure><img src="https://static.platzi.com/media/user_upload/Screenshot%20from%202022-06-03%2011-31-17-1525520c-4cf0-48dd-bbcb-343e03a3c321.jpg" alt="CLI Angular Guards.png"><figcaption></figcaption></figure>

Al auto generar el código, verás tu primer Guard con el siguiente aspecto.

```javascript
// modules/shared/guards/admin.guard.ts
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class AdminGuard implements CanActivate {

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
    return true;
  }

}
```

Un Guard puede devolver un booleano, una promesa con un booleano o un observable, también con un booleano. Dependiendo la lógica que tengas que aplicar para el caso sea síncrona o asíncrona.

### 2. Importando el guard

Ahora importa el nuevo Guard el routing de tu aplicación.

```javascript
// app-routing.module.ts
import { AdminGuard } from './modules/shared/guards/admin.guard';

const routes: Routes = [
  {
    path: '',
    loadChildren: () => import('./modules/website/website.module').then(m => m.WebsiteModule),
    data: { preload: true },
  },
  {
    path: 'cms',
    loadChildren: () => import('./modules/cms/cms.module').then(m => m.CmsModule),
    canActivate: [ AdminGuard ],
    data: { preload: true },
  }
];
```

Agrégale a las rutas que quieras segurizar `canActivate: [ AdminGuard ]`.\
De esta manera, ya puedes implementar la lógica que necesites para cada Guard. En este caso, permitir el acceso al módulo CMS, por ejemplo, solo para usuarios administradores.
