Az Angular Ivy, az új és fejlettebb kompilációs rendszer, számos előnnyel jár a hagyományos View Engine-hez képest, különösen az Ahead-of-Time (AOT) kompilációval kapcsolatban. Az Ivy Instruction Set, amely lehetővé teszi az alkalmazások gyorsabb futtatását, sokkal jobban optimalizálható, mivel a szükséges utasításokat előre kiválogatja és csak a ténylegesen használt kódot tartalmazza a produkciós csomagban. Ezzel szemben a View Engine kódja minden egyes futtatáskor újra kell, hogy értelmezze az adatstruktúrákat, hogy utasításokat generáljon.

A fejlesztési folyamat során az AOT kompiláció jelentős időmegtakarítást eredményez, mivel az Angular előre lefordítja a komponens sablonokat és metainformációkat a build idején. Ez nemcsak a futtatási sebességet növeli, hanem csökkenti a bundle méretét is, mivel a futtatás során nem szükséges a kompilátor betöltése. Az AOT kompilátor használata lehetővé teszi a gyorsabb alkalmazásindítást és a fejlesztési ciklusok gyorsulását, miközben a tesztelési idő is jelentősen csökkenthető.

Azonban az AOT kompiláció alkalmazása néhány korlátozással jár, amelyek fontosak lehetnek a fejlesztők számára. Az egyik legnagyobb kihívás a dinamikusan létrehozott deklarálható elemek (például direktívák, komponensek és pipe-ok) kezelése. Mivel az AOT kompiláció előtt minden deklarációt le kell fordítani, a futás közbeni információk nem használhatók, így nem lehet dinamikusan új deklarációkat létrehozni a runtime-ban. Például, ha a konfigurációk vagy környezeti változók alapján dinamikusan akarunk komponenseket vagy direktívákat betölteni, azt nem lehet közvetlenül az AOT kompilációval megoldani. Az ilyen típusú igények kielégítése érdekében a fejlesztőknek alternatív megoldásokat kell alkalmazniuk, például az Angular futtatókörnyezeti információk dinamikus betöltését szolgáló szolgáltatásokat.

A fejlesztési hibák, amelyek az AOT kompilációval kapcsolatban felmerülhetnek, gyakran a komponens sablonok és Angular metaadatok hibás típusellenőrzéséből adódnak. Az ilyen hibák elkerülése érdekében a szigorú sablon típusellenőrzés engedélyezése ajánlott, ami lehetővé teszi a legtöbb típushibát már a fejlesztés alatt való felismerését, és segít megelőzni a futás közbeni hibák megjelenését.

Az AOT kompilációval kapcsolatban egy másik gyakori korlátozás a függőség-injektálás dinamikus kezelése. Bár a szolgáltatások és osztályok függőségei a futtatási időben is kezelhetők, az aszinkron függőségek kezeléséhez megfelelő szintaktikai megoldásokat kell alkalmazni, például osztályalapú szolgáltatásokat, ígéreteket vagy observable-okat kell használni.

A funkcionalitások deklarálása a metainformációkban is okozhat problémákat. Ha például egy funkciót használunk a metainformációk, például a modult deklaráló imports vagy declarations meghatározására, akkor előfordulhat, hogy a fordító hibát jelez, mivel az AOT kompiláció nem támogatja a dinamikus kifejezéseket, vagy a függvények többszörös visszatérési értékeit. Ilyen esetekben az ilyen kódokat át kell alakítani úgy, hogy az AOT követelményeinek megfelelő egyetlen kifejezés legyen.

Fontos megjegyezni, hogy a szigorú típusellenőrzés engedélyezése az Angular Ivy-ben jelentősen csökkenti a potenciális hibák számát, de az AOT kompiláció további megkötéseket is jelent, amelyeket nem minden esetben lehet könnyen megoldani. Az Angular keretrendszer a jövőben várhatóan további optimalizálásokat vezet be, amelyek segítenek kiküszöbölni az AOT kompilációval kapcsolatos problémákat, miközben fenntartják az alkalmazás teljesítményének és gyorsaságának előnyeit.

Végül, bár az AOT kompiláció számos előnnyel jár, a fejlesztőknek alaposan meg kell érteniük, hogyan érinthetik ezek a korlátozások az alkalmazásuk fejlesztését. A megfelelő eszközök, mint a szigorú típusellenőrzés és az Angular Language Service, segíthetnek minimalizálni az AOT-hoz kapcsolódó problémákat, és biztosítani, hogy a végső alkalmazás zökkenőmentesen működjön a felhasználók számára. Az AOT kompiláció révén csökkentett bundle méret, gyorsabb betöltés és jobb teljesítmény biztosítja, hogy az alkalmazások a lehető legjobban használják ki az Angular adta lehetőségeket.

Hogyan optimalizálhatjuk a globális támogatást a jobb globalizációs API-kkal az Angular-ban?

Az Angular alkalmazások fejlesztése során gyakran felmerül a kérdés, hogyan támogathatjuk a különböző nyelvi és kulturális sajátosságokat, hogy az alkalmazás minden felhasználó számára megfelelően működjön, függetlenül attól, hogy hol élnek, milyen nyelvet beszélnek, vagy melyik írásiránnyal dolgoznak. Az egyik legfontosabb tényező a helyi beállítások és az írásirány kezelése, amely különösen fontos a jobbról balra (RTL) és balról jobbra (LTR) író nyelvek támogatásában.

A megoldás érdekében, amellett, hogy az Angular alapértelmezett nemzetközi API-jait használjuk, képesek vagyunk dinamikusan beállítani az írásirányt a felhasználói felületre. Az Angular által kínált globális API-k és a megfelelő szolgáltatások segítségével egyszerűen módosíthatjuk a dir attribútumot az alkalmazás gyökérelemében, és alkalmazhatjuk a kívánt helyi beállításokat.

Például, mivel nem alkalmazhatunk direktívát közvetlenül a gyökérelemre, létrehozhatunk egy szolgáltatást, amelyet a gyökérkomponensbe injektálhatunk, hogy kezeljük az alkalmazás kezdeti mellékhatásait. A következő kód egy ilyen szolgáltatás példáját mutatja be, amely az @angular/cdk/bidi és @angular/common csomagok segítségével kezeli a kívánt írásirányt:

typescript
import { Component } from '@angular/core';
import { HostDirectionService } from './shared/ui/host-direction.service';
@Component({ selector: 'app-root', template: '', viewProviders: [HostDirectionService], }) export class AppComponent { constructor( // A HostDirectionService injektálása hostDirection: HostDirectionService ) {} }

A következő lépésben, mivel rendelkezünk egy olyan szolgáltatással, amely egy megfigyelhető locale$ tulajdonságot kínál, létrehozhatunk egy HostDirectionService nevű szolgáltatást, amely az aktuális helyi beállításokat és az írásirányt kezeli.

typescript
import { Direction } from '@angular/cdk/bidi'; import { getLocaleDirection } from '@angular/common'; import { ElementRef, Injectable, OnDestroy, Renderer2 } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { map, takeUntil } from 'rxjs/operators'; @Injectable() export class HostDirectionService implements OnDestroy { #destroy = new Subject();
#direction$: Observable = this.localeState
.
locale$.pipe( map((locale) => getLocaleDirection(locale)) ); constructor( private localeState: LocaleStateService, private host: ElementRef, private renderer: Renderer2 ) { this.#direction$ .pipe(takeUntil(this.#destroy))
.subscribe((direction) => this.setHostDirection(direction));
}
ngOnDestroy(): void { this.#destroy.next(); this.#destroy.complete(); } private setHostDirection(direction: Direction): void { this.renderer.setAttribute(this.host.nativeElement, 'dir', direction); } }

Ebben a példában a Renderer2 szolgáltatást használjuk arra, hogy dinamikusan módosítsuk a gyökérelem dir attribútumát. Ezáltal az alkalmazás írásirányát megfelelően beállíthatjuk a különböző helyi beállítások szerint.

A következő lépésben, ha az alkalmazásunk különböző képeket vagy tartalmakat jelenít meg, érdemes lehet dinamikusan betölteni azokat az aktuális írásirány szerint. Az Angular-ban a média lekérdezésekhez hasonló szintaxist hozhatunk létre, hogy a képek megfelelően legyenek betöltve, például a következő kód segítségével:

typescript
import { Direction } from '@angular/cdk/bidi'; import { getLocaleDirection } from '@angular/common';
import { Directive, EmbeddedViewRef, Input, OnDestroy, OnInit, TemplateRef, ViewContainerRef } from '@angular/core';
import { Subject } from 'rxjs'; import { distinctUntilChanged, filter, map, takeUntil, withLatestFrom } from 'rxjs/operators'; import { LocaleStateService } from '../../locale/data-access/locale-state.service'; const directionQueryPattern = /^\(dir: (?ltr|rtl)\)$/; @Directive({ exportAs: 'bidiMedia', selector: '[media]', }) export class BidiMediaDirective implements OnDestroy, OnInit {
#appDirection$ = this.localeState.locale$.pipe(
map((locale) => getLocaleDirection(locale)) ); #destroy = new Subject(); #queryDirection = new Subject(); #queryDirection$ = this.#queryDirection.pipe(distinctUntilChanged()); #validState$ = this.#queryDirection$.pipe( withLatestFrom(this.#appDirection$), map(([queryDirection, appDirection]) => ({ appDirection, queryDirection, })), filter( ({ appDirection, queryDirection }) => appDirection !== undefined && queryDirection !== undefined ) ); #view?: EmbeddedViewRef; @Input() set media(query: string) { if (!this.isDirection(query)) { throw new Error( `Invalid direction media query "${query}". Use format "(dir: ltr|rtl)"` ); }
this.#queryDirection.next(this.queryToDirection(query));
}
constructor( private template: TemplateRef, private container: ViewContainerRef, private localeState: LocaleStateService ) {} ngOnInit(): void { this.attachElementOnDirectionMatch(); this.removeElementOnDirectionMismatch(); } ngOnDestroy(): void { this.#destroy.next(); this.#destroy.complete(); } private attachElement(): void { if (this.#view) { return; } this.#view = this.container.createEmbeddedView(this.template); } private attachElementOnDirectionMatch(): void { const directionMatch$ = this.#validState$.pipe( filter( ({ appDirection, queryDirection }) => queryDirection === appDirection ) ); directionMatch$ .pipe(takeUntil(this.#destroy)) .subscribe(() => this.attachElement()); }
private isDirection(query: string): boolean {
return directionQueryPattern.test(query); } private queryToDirection(query: string): Direction {
return query.includes('ltr') ? 'ltr' : 'rtl';
} }

Ez a kód egy olyan struktúrális direktívát mutat be, amely az aktuális alkalmazás írásirányának megfelelően jeleníti meg vagy rejti el a tartalmat. Az alkalmazás irányát figyelő logika és az irányváltások kezelése lehetővé teszi, hogy az alkalmazás dinamikusan alkalmazkodjon a felhasználó környezetéhez.

Fontos, hogy az Angular által nyújtott lehetőségek és eszközök alkalmazása során mindig figyeljünk a teljes globális támogatásra. Az írásirány mellett más kulturális eltérések is befolyásolhatják az alkalmazás megjelenését és működését, például az időformátumok, pénznemek, dátumok, vagy éppen a szövegek, amelyek a nyelvek közötti különbségeket tükrözik.