Angular 14.2 brings best practices in handling images and standalone routing

0
32
angular 142 brings best practices in handling images and standalone.jpg
angular 142 brings best practices in handling images and standalone.jpg

The web framework extends the standalone API and, as the biggest innovation, brings a new directive called NgOptimizedImage.

 

The current main version, Angular 14, brought standalone components with it for the first time, which made the use of NgModule optional. Almost three months after the release, Angular 14.2 was released as the second minor version and extends the standalone API to include the router. As the biggest change, however, the release brings a new directive under the name NgOptimizedImage With.

 

Optimizing the bundle size – the bundle is the JavaScript file(s) of the front-end application – is a very time-consuming and demanding activity for developers. But the smaller the file, the faster the application can be started in the browser.

It should be noted that a browser does not only load JavaScript files. Images, especially full-screen ones, can make up multiples of a bundle. This is particularly painful when the image in question is not even in the viewport and is therefore not needed for the initial loading.

Here comes the new directive NgOptimizedImage in the game. To activate it is in <img> the attribute src through rawSrc exchange.

 

<!-- ohne NgOptimizedImage -->
<img [src]="'/assets/' + holiday.imageUrl" [alt]="holiday.title" />

<!-- mit NgOptimizedImage -->
<img [rawSrc]="'/assets/' + holiday.imageUrl" [alt]="holiday.title" />

 

Listing 1: Activation of NgOptimizedImage

With Listing 1, the new directive already carries out various checks. Should the attributes for width or height are missing, the picture is not displayed, but an error message appears. The omission of the dimension information leads to the so-called content shifting or cumulative layout shift (CLS) according to Core Web Vitals. The layout is shifted by the subsequent loading of the images. This is not a good user experience and can be easily avoided by setting the attributes.

Furthermore, each image is loaded lazy by default. That is, the browser knows that the developers do not count the image among the critical elements. This can mean that images located far outside the viewport are only loaded when required.

In the example used, this behavior can be displayed via the network tab in the DevTools. Only the first three out of ten images are loaded. The browser only reloads when you scroll down.

 

Best practices require that the “critical images” that reside in the viewport be identified via the attribute priority to be marked as such. However, if you forget to do this, the directive with a warning message will also help in this case. However, it is only used during development mode (ng serve) shown.

 

@Component({
  template: `<div *ngFor="let holiday of holidays; first as isFirst">
    <h3>{{ holiday.title }}</h3>
    <img
      [rawSrc]="'/assets/' + holiday.imageUrl"
      [alt]="holiday.title"
      [priority]="isFirst ? 'priority' : 'false'"
      width="1920"
      height="1080"
    />
  </div>`,
  imports: [NgForOf, NgOptimizedImage],
  standalone: true,
})
export class OptimizedComponent {
  // ...
}

 

Listing 2: Standalone component with NgOptimizedImage that prioritizes the first image

There is also the option of specifying Content Delivery Networks (CDN) that automatically provide image scaling. This can be set in Angular using a loader function. Again, Angular ensures that the CDN URL with preconnect has been set. If not, a warning message appears again.

 

@Component({ template: `

Optimized Version with Cloudinary CDN

{{ holiday.title }}

< img [rawSrc]=”‘/angular-14-2/’ + holiday.imageUrl” [alt]=”holiday.title” [priority]=”isFirst ? ‘priority’ : ‘false'” width=”1920″ height=”1080″ />

`, imports: [NgForOf, NgOptimizedImage]providers: [provideCloudinaryLoader(” standalone: true, }) export class CdnComponent { holidays = holidays; }

 

Listing 3: Komponente mit Bildern von Cloudify

Vor allem für Angular-Anwendungen, die sehr stark mit Bildern arbeiten, ist diese neue Direktive ein wahrer Segen. In den nächsten Releases sollen weitere Features folgen.

Neben der neuen Direktive bringt Angular 14.2 auch Standalone APIs. Standalone Components (mit Pipes und Directives) tragen bekanntlich durch das Weglassen von NgModules zu einer Verringerung des Boilerplate-Codes bei. Es ist zwar schön, seinen eigenen Code ohne NgModules schreiben zu können, man trifft sie aber immer dann an, wenn man Funktionen des Frameworks wie RouterModule, ReactiveFormsModule, HttpClientModule oder Drittbibliotheken verwendet.

Die Standalone API schickt sich an, Alternativimplementierungen zu den NgModule-basierten Funktionen anzubieten.

Mit Angular 14.2 wurde das RouterModule samt Direktiven zu Standalone migriert. Das heißt, es ist jetzt nicht mehr notwendig, bei der Konfiguration der Routen RouterModule.forRoot oder forChild zu verwenden. Als Alternative gibt es die Funktion provideRouter.

 

bootstrapApplication(AppComponent, {
  providers: [
    provideRouter(routes),
    importProvidersFrom(
      BrowserAnimationsModule,
      // RouterModule.forRoot(routes), <-- durhc provideRouter (oben) ersetzt
      HttpClientModule
    ),
  ]});

 

Listing 4: The provideRouter function in use

The directives associated with routing such as routerLink is now available as a standalone version. You can now, with appropriate use, instead of the RouterModule easy RouterLinkWithHref in the imports Add and the directive is ready to use.

 

@Component({
  template: `<ul>
    <li>
      <a mat-raised-button routerLink="/optimized">Optimized</a>
    </li>
  </ul> `,
  styleUrls: ["./sidemenu.component.scss"],
  standalone: true,
  imports: [CommonModule, MatButtonModule, RouterLinkWithHref],
})
export class SidemenuComponent {}

 

Listing 5: Component with standalone routerLink

All in all, Angular 14.2 is a well-rounded affair and contains above all NgOptimizedImage new features on a scale that you didn’t even have with previous major releases. An upgrade is therefore worthwhile in any case.