Today I Learned

TIL, 2022-11-29, Angular 15

Angular’s Future Without NgModules – Part 1: Lightweight Solutions Using Standalone Components

Reference

Angular’s Future Without NgModules – Part 2: What Does That Mean for Our Architecture?

Reference

Routing and Lazy Loading with Angular’s Standalone Components

Reference

  • Why again? Because we needed a way to group building blocks that are used together - for devs and for the Angular compiler. This is so the Angular compiler knows which things are supposed to compile.
    • Community not happy, because it becomes another module system besides ECMAScript.
    • Ivy - The compiled application works without modules at runtime.
  • With standalone components, it will be possible to bootstrap a single component via bootstrapApplication.
    • importProvidersFrom - allows bridging the gap to existing NgModules.
bootstrapApplication(AppComponent, {
  providers: [
    importProvidersFrom(HttpClientModule),
    provideRouter(APP_ROUTES,
      withPreloading(PreloadAllModules),
      withDebugTracing(),
    ),

    [...]

    importProvidersFrom(TicketsModule),
    provideAnimations(),
    importProvidersFrom(LayoutModule),
  ]
});
  • You can lazily load a component directly:
    // Option 1: Lazy Loading another Routing Config
    {
        path: 'flight-booking',
        loadChildren: () =>
            import('./booking/flight-booking.routes')
                .then(m => m.FLIGHT_BOOKING_ROUTES)
    },

    // Option 2: Directly Lazy Loading a Standalone Component
    {
        path: 'next-flight',
        loadComponent: () =>
            import('./next-flight/next-flight.component')
                .then(m => m.NextFlightComponent)
    },
  • Services for specific routes: With NgModule, each lazy module introduced a new injector and hence a new injection scope. To cover such cases, you can now add introducing providers for each route.
export const FLIGHT_BOOKING_ROUTES: Routes = [{
    path: '',
    component: FlightBookingComponent,
    providers: [
        provideBookingDomain(config)
    ],
  • Technically, adding providers introduces a new injector at the level of the route. Such an injector is called Environment Injector and replaces the concept of the former NgModule injectors.
  • NgRx: Can do provideStore, provideEffects now.
import { provideStore } from '@ngrx/store';
import { provideEffects } from '@ngrx/effects';
import { provideStoreDevtools } from '@ngrx/store-devtools';

import { reducer } from './app/+state';

[...]

bootstrapApplication(AppComponent, {
  providers: [
    importProvidersFrom(HttpClientModule),
    provideRouter(APP_ROUTES,
      withPreloading(PreloadAllModules),
      withDebugTracing(),
    ),

    // Setup NGRX:
    provideStore(reducer),
    provideEffects([]),
    provideStoreDevtools(),
  • Can also have provideState and provideEffects in the respective routing configuration.
  • ENVIRONMENT_INITIALIZER: a function executed when the environment injector is initialized.

Angular v15 is now available!

Reference

  • Standalone APIs are out of the developer preview.
  • Router and HttpClient are tree-shakeable standalone APIs.
  • provideRouter is tree-shakeable (!).
  • Directive composition: Adding directives to a host element via hostDirectives.
  • Image directive is now stable - automatic srcset generation (ngOptimizedImage).
  • Functional router guards.
  • Router unwraps default imports.
  • Auto-unwrapping the standalone component
{
  path: 'lazy',
  loadComponent: () => import('./lazy-file').then(m => m.LazyComponent),
}

to

{
  path: 'lazy',
  loadComponent: () => import('./lazy-file'),
}
  • Refactoring Angular material components based on Material Design Components for Web.
  • Moving some components to use design tokens and CSS variables under the hood.
  • esbuild.

This project is maintained by daryllxd