typescript 42 lines · 8 steps

Route-scoped providers and lazy loading in Angular

A feature route tree that scopes its own services, lazy-loads components, and resolves data with functional route guards.

Explained by highlit
1import { Routes } from '@angular/router';
2import { inject } from '@angular/core';
3import { HttpClient } from '@angular/common/http';
4import { REPORT_API_URL } from './reports/report.tokens';
5import { ReportStore } from './reports/report.store';
6import { canDeactivateReport } from './reports/report.guard';
7 
8export const reportRoutes: Routes = [
9 {
10 path: 'reports',
11 providers: [
12 ReportStore,
13 { provide: REPORT_API_URL, useValue: '/api/v2/reports' },
14 ],
15 loadComponent: () =>
16 import('./reports/report-shell.component').then((m) => m.ReportShellComponent),
17 children: [
18 {
19 path: '',
20 pathMatch: 'full',
21 loadComponent: () =>
22 import('./reports/report-list.component').then((m) => m.ReportListComponent),
23 resolve: {
24 summaries: () => inject(ReportStore).loadSummaries(),
25 },
26 },
27 {
28 path: ':id',
29 canDeactivate: [canDeactivateReport],
30 loadComponent: () =>
31 import('./reports/report-detail.component').then((m) => m.ReportDetailComponent),
32 resolve: {
33 report: (route) => {
34 const http = inject(HttpClient);
35 const url = inject(REPORT_API_URL);
36 return http.get(`${url}/${route.paramMap.get('id')}`);
37 },
38 },
39 },
40 ],
41 },
42];
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Attaching providers to a route scopes services and tokens to that route subtree instead of the whole app.
  2. 2loadComponent defers a component's code until the route activates, shrinking the initial bundle.
  3. 3Functional resolvers and guards use inject() to pull dependencies without a constructor or class.

Related explainers

typescript
import { registerLocaleData } from '@angular/common';
import localeFr from '@angular/common/locales/fr';
import localeFrExtra from '@angular/common/locales/extra/fr';
import localeDe from '@angular/common/locales/de';

Locale-aware bootstrapping in Angular

i18n localization dependency-injection
Intermediate 8 steps
typescript
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import * as Joi from 'joi';
 

Validating env config at boot in NestJS

configuration schema-validation environment-variables
Intermediate 8 steps
java
@Component
@Converter
public class EncryptedStringConverter implements AttributeConverter<String, String> {
 

Transparent column encryption in Spring & JPA

encryption aes-gcm jpa-converter
Advanced 10 steps
typescript
import { Inject, Injectable, Logger } from '@nestjs/common';
import { CACHE_MANAGER } from '@nestjs/cache-manager';
import { Cache } from 'cache-manager';
import { InjectRepository } from '@nestjs/typeorm';

A cache-aside country lookup in NestJS

cache-aside dependency-injection batch-lookup
Intermediate 8 steps
java
package com.acme.billing.config;
 
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;

Feature-flagged beans with Spring @ConditionalOnProperty

feature-flags conditional-beans strategy-pattern
Intermediate 5 steps
typescript
import { Injectable, effect, signal, computed } from '@angular/core';
 
interface Preferences {
  theme: 'light' | 'dark';

A signal-based preferences store in Angular

signals state-management persistence
Intermediate 7 steps

Share this explainer

Here's the card — post it anywhere.

Route-scoped providers and lazy loading in Angular — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code