Tüm Avantajlar, Sorunsuz: Angular 9 Eğitimi

Yayınlanan: 2022-03-11

"İnternet her yıl bozulur" der ve geliştiricilerin genellikle gidip düzeltmeleri gerekir. Uzun zamandır beklenen Angular sürüm 9 ile bunun geçerli olacağı ve önceki sürümlerde geliştirilen uygulamaların büyük bir geçiş sürecinden geçmesi gerektiği düşünülebilir.

Ama durum böyle değil! Angular ekibi, derleyicisini tamamen yeniden tasarlayarak daha hızlı derlemeler, daha hızlı test çalıştırmaları, daha küçük paket boyutları ve en önemlisi eski sürümlerle geriye dönük uyumluluk sağladı. Angular 9 ile geliştiriciler temel olarak tüm avantajları herhangi bir güçlük çekmeden elde eder.

Bu Angular 9 eğitiminde, sıfırdan bir Angular uygulaması oluşturacağız. En yeni Angular 9 özelliklerinden bazılarını kullanacağız ve yol boyunca diğer iyileştirmeleri gözden geçireceğiz.

Angular 9 Eğitimi: Yeni Bir Angular Uygulamasıyla Başlamak

Angular proje örneğimize başlayalım. İlk olarak, Angular'ın CLI'sinin en son sürümünü yükleyelim:

 npm install -g @angular/cli

Angular CLI versiyonunu ng version çalıştırarak doğrulayabiliriz.

Ardından, bir Angular uygulaması oluşturalım:

 ng new ng9-app --create-application=false --strict

ng new komutumuzda iki argüman kullanıyoruz:

  • --create-application=false , CLI'ye yalnızca çalışma alanı dosyaları oluşturmasını söyler. Bu, birden fazla uygulamaya ve birden fazla kitaplığa ihtiyacımız olduğunda kodumuzu daha iyi düzenlememize yardımcı olacaktır.
  • --strict , daha fazla TypeScript yazmayı ve kod temizliğini zorlamak için daha katı kurallar ekler.

Bunun sonucunda elimizde temel bir workspace klasör ve dosyalarımız oluyor.

node_modules, .editorconfig, .gitignore, angular.json, package-lock.json, package.json, README.md, tsconfig.json ve tslint.json içeren ng9-app klasörünü gösteren bir IDE ekran görüntüsü.

Şimdi yeni bir uygulama ekleyelim. Bunu yapmak için çalıştıracağız:

 ng generate application tv-show-rating

Sorulacak:

 ? Would you like to share anonymous usage data about this project with the Angular Team at Google under Google's Privacy Policy at https://policies.google.com/privacy? For more details and how to change this setting, see http://angular.io/analytics. No ? Would you like to add Angular routing? Yes ? Which stylesheet format would you like to use? SCSS

Şimdi, ng serve 'yi çalıştırırsak, uygulamanın ilk iskelesi ile çalıştığını göreceğiz.

Angular 9'un yapı iskelesinin bir ekran görüntüsü, "televizyon programı derecelendirme uygulaması çalışıyor!" Ayrıca kaynaklara ve sonraki adımlara bağlantılar da vardır.

ng build --prod çalıştırırsak, oluşturulan dosyaların listesini görebiliriz.

Angular 9'un "ng build --prod" çıktısının ekran görüntüsü. "Diferansiyel yükleme için ES5 paketleri oluşturuluyor..." ile başlar. Bunu yaptıktan sonra, her biri -es2015 ve -es5 sürümüne sahip çalışma zamanı, çoklu dolgular ve ana olmak üzere birkaç JavaScript dosya parçası ve bir CSS dosyası listeler. Son satır bir zaman damgası, karma ve 23.881 milisaniyelik bir çalışma zamanı verir.

Her dosyanın iki versiyonu var. Biri eski tarayıcılarla uyumludur ve diğeri, daha yeni API'ler kullanan ve tarayıcılarda çalıştırmak için daha az çoklu dolgu gerektiren ES2015'i hedefleyen derlenmiştir.

Angular 9'daki büyük gelişmelerden biri paket boyutudur. Angular ekibine göre büyük uygulamalarda %40'a varan düşüşler görebilirsiniz.

Yeni oluşturulan bir uygulama için paket boyutu, Angular 8'inkine oldukça benzer, ancak uygulamanız büyüdükçe, paket boyutunun önceki sürümlere göre küçüldüğünü göreceksiniz.

Angular 9'da tanıtılan bir diğer özellik, bileşen stili CSS dosyalarından herhangi biri tanımlanmış bir eşikten büyükse bizi uyarma yeteneğidir.

Bir dizide iki nesne bulunan bir Angular 9 JSON yapılandırma dosyasının "bütçeler" bölümünün ekran görüntüsü. İlk nesnede "type", "initial", "maximumWarning" "2mb" ve "maximumError" "5mb" olarak ayarlanmıştır. İkinci nesnede "type", "anyComponentStyle", "maximumWarning" "6kb" ve "maximumError" "10kb" olarak ayarlanmıştır.

Bu, kötü stil içe aktarmalarını veya çok büyük bileşen stili dosyalarını yakalamamıza yardımcı olacaktır.

TV Şovlarını Derecelendirmek için Form Ekleme

Ardından, TV şovlarını derecelendirmek için bir form ekleyeceğiz. Bunun için önce bootstrap ve ng-bootstrap yükleyeceğiz:

 npm install bootstrap @ng-bootstrap/ng-bootstrap

Angular 9'daki bir başka gelişme de i18n'dir (uluslararasılaştırma). Önceden, geliştiricilerin bir uygulamadaki her yerel ayar için tam bir derleme çalıştırması gerekirdi. Bunun yerine Angular 9, bir uygulamayı bir kez oluşturmamıza ve tüm i18n dosyalarını derleme sonrası bir süreçte oluşturmamıza olanak tanıyarak derleme süresini önemli ölçüde azaltır. ng-bootstrap i18n'ye bağımlı olduğundan, yeni paketi projemize ekleyeceğiz:

 ng add @angular/localize

Ardından, Bootstrap temasını uygulamamızın styles.scss :

 @import "~bootstrap/scss/bootstrap";

NgbModule ve ReactiveFormsModule AppModule app.module.ts :

 // ... import { ReactiveFormsModule } from '@angular/forms'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; @NgModule({ imports: [ // ... ReactiveFormsModule, NgbModule ], })

Ardından, app.component.html formumuz için temel bir ızgarayla güncelleyeceğiz:

 <div class="container"> <div class="row"> <div class="col-6"> </div> </div> </div>

Ve form bileşenini oluşturun:

 ng gc TvRatingForm

tv-rating-form.component.html güncelleyelim ve TV şovlarını derecelendirmek için formu ekleyelim.

 <form [formGroup]="form" (ngSubmit)="submit()" class="mt-3"> <div class="form-group"> <label>TV SHOW</label> <select class="custom-select" formControlName="tvShow"> <option *ngFor="let tvShow of tvShows" [value]="tvShow.name">{{tvShow.name}}</option> </select> </div> <div class="form-group"> <ngb-rating [max]="5" formControlName="rating"></ngb-rating> </div> <button [disabled]="form.invalid || form.disabled" class="btn btn-primary">OK</button> </form>

Ve tv-rating-form.component.ts görünecektir:

 // ... export class TvRatingFormComponent implements OnInit { tvShows = [ { name: 'Better call Saul!' }, { name: 'Breaking Bad' }, { name: 'Lost' }, { name: 'Mad men' } ]; form = new FormGroup({ tvShow: new FormControl('', Validators.required), rating: new FormControl('', Validators.required), }); submit() { alert(JSON.stringify(this.form.value)); this.form.reset(); } }

Son olarak, formu app.component.html :

 <!-- ... --> <div class="col-6"> <app-tv-rating-form></app-tv-rating-form> </div>

Bu noktada, bazı temel UI işlevlerine sahibiz. Şimdi, tekrar servisi çalıştırırsak, ng serve görebiliriz.

"TV Şovu" başlıklı bir formu gösteren ve bir avuç gösteri başlığını, bir yıldız ölçeri ve bir Tamam düğmesini listeleyen bir açılır listeyle birlikte Angular 9 eğitim uygulamasının ekran görüntüsü. Animasyonda, kullanıcı bir gösteri seçer, bir derecelendirme seçer ve ardından Tamam düğmesini tıklar.

Devam etmeden önce, hata ayıklamaya yardımcı olmak için eklenen bazı ilginç yeni Angular 9 özelliklerine hızlıca göz atalım. Bu günlük işimizde çok yaygın bir görev olduğundan, hayatımızı biraz daha kolaylaştırmak için neyin değiştiğini bilmeye değer.

Angular 9 Ivy ile hata ayıklama

Angular 9 ve Angular Ivy'de sunulan bir diğer büyük gelişme de hata ayıklama deneyimidir. Derleyici artık daha fazla hata algılayabilir ve bunları daha "okunabilir" bir şekilde atabilir.

Eylemde görelim. İlk olarak, tsconfig.json şablon kontrolünü etkinleştireceğiz:

 { // ... "angularCompilerOptions": { "fullTemplateTypeCheck": true, "strictInjectionParameters": true, "strictTemplates": true } }

Şimdi, tvShows dizisini güncellersek ve name title olarak değiştirirsek:

 tvShows = [ { title: 'Better call Saul!' }, { title: 'Breaking Bad' }, { title: 'Lost' }, { title: 'Mad men' } ];

…derleyiciden bir hata alacağız.

Bir dosya adı ve konumu ile Angular 9/Angular Ivy derleyici çıktısının ekran görüntüsü, "hata TS2339: Özellik 'adı' '{ başlık: dize; }' türünde mevcut değil." Ayrıca söz konusu kod satırını gösterir ve referansın altını çizer, bu durumda tvShow.name'nin geçtiği tv-rating-form.component.html dosyasında. Bundan sonra, bu HTML dosyasına yapılan referans, ilgili TypeScript dosyasına kadar izlenir ve benzer şekilde vurgulanır.

Bu tür denetimi, yazım hatalarını ve TypeScript türlerinin yanlış kullanımını önlememizi sağlar.

@Input() için Angular Ivy Doğrulaması

Aldığımız bir başka iyi doğrulama da @Input() ile. Örneğin, bunu tv-rating-form.component.ts :

 @Input() title: string;

…ve onu app.component.html :

 <app-tv-rating-form [title]="title"></app-tv-rating-form>

…ve ardından app.component.ts şu şekilde değiştirin:

 // ... export class AppComponent { title = null; }

Bu üç değişikliği yaparsak, derleyiciden başka bir tür hata alırız.

Angular 9/Angular Ivy derleyici çıktısının, öncekine benzer bir biçimde, app.component.html'yi "hata TS 2322: 'null' türü, 'string' yazmak için atanamaz" ile vurgulayan bir ekran görüntüsü.

Bunu atlamak istersek, değeri any çevirmek ve hatayı düzeltmek için şablonda $any() kullanabiliriz :

 <app-tv-rating-form [title]="$any(title)"></app-tv-rating-form>

Bununla birlikte, bunu düzeltmenin doğru yolu, formdaki title geçersiz kılmak olacaktır:

 @Input() title: string | null ;

Angular 9 ExpressionChangedAfterItHasBeenCheckedError İfadeChangedAfterItHasBeenCheckedError

Angular geliştirmedeki en korkunç hatalardan biri ExpressionChangedAfterItHasBeenCheckedError . Neyse ki, Ivy hatayı daha net bir şekilde verir ve sorunun nereden geldiğini bulmayı kolaylaştırır.

Öyleyse, bir ExpressionChangedAfterItHasBeenCheckedError hatası verelim. Bunu yapmak için önce bir hizmet üreteceğiz:

 ng gs Title

Ardından, bir BehaviorSubject ve Observable erişmek ve yeni bir değer yaymak için yöntemler ekleyeceğiz.

 export class TitleService { private bs = new BehaviorSubject < string > (''); constructor() {} get title$() { return this.bs.asObservable(); } update(title: string) { this.bs.next(title); } }

Bundan sonra, bunu app.component.html :

 <!-- ... --> <div class="col-6"> <h2> {{title$ | async}} </h2> <app-tv-rating-form [title]="title"></app-tv-rating-form> </div>

Ve app.component.ts içinde TitleService öğesini enjekte edeceğiz:

 export class AppComponent implements OnInit { // ... title$: Observable < string > ; constructor( private titleSvc: TitleService ) {} ngOnInit() { this.title$ = this.titleSvc.title$; } // ... }

Son olarak, tv-rating-form.component.ts içinde TitleService enjekte edeceğiz ve bir ExpressionChangedAfterItHasBeenCheckedError hatası verecek olan AppComponent başlığını güncelleyeceğiz.

 // ... constructor( private titleSvc: TitleService ) { } ngOnInit() { this.titleSvc.update('new title!'); }

Artık ayrıntılı hatayı tarayıcının geliştirme konsolunda görebiliriz ve app.component.html tıklamak bizi hatanın nerede olduğunu gösterir.

Angular Ivy'nin ExpressionChangedAfterItHasBeenCheckedError hatasını bildirdiğini gösteren tarayıcının geliştirme konsolunun ekran görüntüsü. Kırmızı metindeki yığın izleme, önceki ve geçerli değerlerle birlikte hatayı ve bir ipucu verir. Yığın izinin ortasında, core.js'ye atıfta bulunmayan tek satır bulunur. Kullanıcı bunu tıklatır ve hataya neden olan app.component.html satırına getirilir.

Servis çağrısını setTimeout ile sararak bu hatayı düzeltebiliriz:

 setTimeout(() => { this.titleSvc.update('new title!'); });

ExpressionChangedAfterItHasBeenCheckedError hatasının neden oluştuğunu anlamak ve diğer olasılıkları keşfetmek için Maxim Koretskyi'nin konuyla ilgili yazısı okunmaya değer.

Angular Ivy, hataların daha net bir şekilde sunulmasını sağlar ve kodumuzda TypeScript yazarak zorlamaya yardımcı olur. Aşağıdaki bölümde, Ivy ve hata ayıklamadan yararlanacağımız bazı yaygın senaryoları ele alacağız.

Bileşen Donanımlarıyla Angular 9 Uygulamamız için Test Yazma

Angular 9'da bileşen koşumları adı verilen yeni bir test API'si tanıtıldı. Bunun arkasındaki fikir, DOM ile etkileşim için gereken tüm işleri ortadan kaldırarak çalışmayı çok daha kolay ve çalıştırmayı daha kararlı hale getirmektir.

Bileşen koşum API'si @angular/cdk kitaplığına dahil edilmiştir, bu yüzden önce bunu projemize yükleyelim:

 npm install @angular/cdk

Artık bir test yazabilir ve bileşen koşumlarından yararlanabiliriz. tv-rating-form.component.spec.ts içinde testi ayarlayalım:

 import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { ReactiveFormsModule } from '@angular/forms'; describe('TvRatingFormComponent', () => { let component: TvRatingFormComponent; let fixture: ComponentFixture < TvRatingFormComponent > ; beforeEach(async (() => { TestBed.configureTestingModule({ imports: [ NgbModule, ReactiveFormsModule ], declarations: [TvRatingFormComponent] }).compileComponents(); })); // ... });

Ardından, bileşenimiz için bir ComponentHarness uygulayalım. İki koşum takımı oluşturacağız: biri TvRatingForm için, diğeri NgbRating için. ComponentHarness , bileşenin seçicisinin değerini alması gereken hostSelector adlı static bir alan gerektirir.

 // ... import { ComponentHarness, HarnessLoader } from '@angular/cdk/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; class TvRatingFormHarness extends ComponentHarness { static hostSelector = 'app-tv-rating-form'; } class NgbRatingHarness extends ComponentHarness { static hostSelector = 'ngb-rating'; } // ...

TvRatingFormHarness için, gönder düğmesi için bir seçici ve bir click tetikleyecek bir işlev oluşturacağız. Bunu uygulamanın ne kadar kolaylaştığını görebilirsiniz.

 class TvRatingFormHarness extends ComponentHarness { // ... protected getButton = this.locatorFor('button'); async submit() { const button = await this.getButton(); await button.click(); } }

Ardından, bir derecelendirme belirlemek için yöntemler ekleyeceğiz. Burada, kullanıcının tıklayabileceği yıldızları temsil eden tüm <span> öğelerini aramak için locatorForAll kullanıyoruz. rate işlevi, yalnızca olası tüm derecelendirmelerin yıldızlarını alır ve gönderilen değere karşılık gelene tıklar.

 class NgbRatingHarness extends ComponentHarness { // ... protected getRatings = this.locatorForAll('span:not(.sr-only)'); async rate(value: number) { const ratings = await this.getRatings(); return ratings[value - 1].click(); } }

Eksik olan son parça, NgbRatingHarness TvRatingFormHarness . Bunu yapmak için, TvRatingFormHarness sınıfına konumlandırıcıyı eklememiz yeterlidir.

 class TvRatingFormHarness extends ComponentHarness { // ... getRating = this.locatorFor(NgbRatingHarness); // ... }

Şimdi testimizi yazalım:

 describe('TvRatingFormComponent', () => { // ... it('should pop an alert on submit', async () => { spyOn(window, 'alert'); const select = fixture.debugElement.query(By.css('select')).nativeElement; select.value = 'Lost'; select.dispatchEvent(new Event('change')); fixture.detectChanges(); const harness = await TestbedHarnessEnvironment.harnessForFixture(fixture, TvRatingFormHarness); const rating = await harness.getRating(); await rating.rate(1); await harness.submit(); expect(window.alert).toHaveBeenCalledWith('{"tvShow":"Lost","rating":1}'); }); });

Form içindeki seçimimiz select değerini bir koşum takımı aracılığıyla ayarlamadığımıza dikkat edin. Bunun nedeni, API'nin hala bir seçenek belirlemeyi desteklememesidir. Ancak bu bize burada, bileşenlerle etkileşimin bileşen kablo demetlerinden önce nasıl göründüğünü karşılaştırma şansı veriyor.

Testleri çalıştırmadan önce son bir şey. title null olarak güncellediğimiz için app.component.spec.ts düzeltmemiz gerekiyor.

 describe('AppComponent', () => { // ... it(`should have as title 'tv-show-rating'`, () => { const fixture = TestBed.createComponent(AppComponent); const app = fixture.componentInstance; expect(app.title).toEqual(null); }); });

Şimdi ng test çalıştırdığımızda testimiz geçiyor.

Angular 9 uygulamamızda Karma çalıştıran testlerin ekran görüntüsü. "Eksik: uygun() veya fdescribe() bulundu, 2 özellik, 0 hata, tohum 69573 ile randomize edildi" mesajıyla birlikte "6 özellikten 2'sini çalıştırdı" gösteriyor. TvRatingFormComponent'in iki testi vurgulanmıştır. AppComponent'in üç testi ve TitleService'in bir testinin tümü gridir.

Angular 9 Örnek Uygulamamıza Geri Dönün: Verileri Veritabanına Kaydetme

Firestore'a bir bağlantı ekleyerek ve derecelendirmeleri veritabanına kaydederek Angular 9 eğitimimizi tamamlayalım.

Bunu yapmak için bir Firebase Projesi oluşturmamız gerekiyor. Ardından, gerekli bağımlılıkları yükleyeceğiz.

 npm install @angular/fire firebase

Firebase Konsolu'nun proje ayarlarında, yapılandırmasını alacağız ve bunları environment.ts ve environment.prod.ts ekleyeceğiz:

 export const environment = { // ... firebase: { apiKey: '{your-api-key}', authDomain: '{your-project-id}.firebaseapp.com', databaseURL: 'https://{your-project-id}.firebaseio.com', projectId: '{your-project-id}', storageBucket: '{your-project-id}.appspot.com', messagingSenderId: '{your-messaging-id}', appId: '{your-app-id}' } };

Bundan sonra, app.module.ts içindeki gerekli modülleri içe aktaracağız:

 import { AngularFireModule } from '@angular/fire'; import { AngularFirestoreModule } from '@angular/fire/firestore'; import { environment } from '../environments/environment'; @NgModule({ // ... imports: [ // ... AngularFireModule.initializeApp(environment.firebase), AngularFirestoreModule, ], // ... })

Ardından, tv-rating-form.component.ts AngularFirestore hizmetini enjekte edeceğiz ve form gönderiminde yeni bir derecelendirme kaydedeceğiz:

 import { AngularFirestore } from '@angular/fire/firestore'; export class TvRatingFormComponent implements OnInit { constructor( // ... private af: AngularFirestore, ) { } async submit(event: any) { this.form.disable(); await this.af.collection('ratings').add(this.form.value); this.form.enable(); this.form.reset(); } } 

Daha büyük bir sayfa başlığı olan "yeni başlık!" altında "TV Şovu" başlıklı bir formu gösteren bir Angular 9 öğretici uygulamasının ekran görüntüsü. Yine, bir avuç gösteri başlığını, bir yıldız ölçeri ve bir Tamam düğmesini listeleyen bir açılır menüye sahiptir ve yine kullanıcı bir gösteri seçer, bir derecelendirme seçer ve ardından Tamam düğmesini tıklar.

Şimdi Firebase Konsoluna gittiğimizde yeni oluşturulan itemi göreceğiz.

Firebase Konsolunun bir ekran görüntüsü. Sol sütunda bazı koleksiyonların bulunduğu joaq-lab var: katılımcılar, yarışlar, derecelendirmeler, testler ve kullanıcılar. Derecelendirme öğesi seçilir ve seçilen bir kimlikle orta sütunda gösterilir; tek belge budur. Sağ sütunda iki alan gösteriliyor: "derecelendirme" 4'e ve "tvShow", "Deli adamlar"a ayarlı.

Son olarak, tüm derecelendirmeleri AppComponent . Bunu yapmak için app.component.ts içinde, koleksiyondaki verileri alacağız:

 import { AngularFirestore } from '@angular/fire/firestore'; export class AppComponent implements OnInit { // ... ratings$: Observable<any>; constructor( // ... private af: AngularFirestore ) { } ngOnInit() { // ... this.ratings$ = this.af.collection('ratings').valueChanges(); } }

…ve app.component.html bir derecelendirme listesi ekleyeceğiz:

 <div class="container"> <div class="row"> // ... <div class="col-6"> <div> <p *ngFor="let rating of ratings$ | async"> {{rating.tvShow}} ({{rating.rating}}) </p> </div> </div> </div> </div>

Angular 9 eğitim uygulamamız bir araya getirildiğinde böyle görünüyor.

Daha büyük bir sayfa başlığı olan "yeni başlık!" altında "TV Şovu" başlıklı bir formu gösteren bir Angular 9 öğretici uygulamasının ekran görüntüsü. Yine, bir avuç gösteri başlığını, bir yıldız ölçeri ve bir Tamam düğmesini listeleyen bir açılır menüye sahiptir. Bu sefer, sağ taraftaki bir sütun zaten "Mad men (4)"ü listeliyor ve kullanıcı Lost'u üç yıldızla ve ardından yine dört yıldızla "Mad men" takip ediyor. Sağdaki sütun, her iki yeni derecelendirmeden sonra alfabetik olarak sıralanır.

Angular 9 ve Angular Ivy: Daha İyi Geliştirme, Daha İyi Uygulamalar ve Daha İyi Uyumluluk

Bu Angular 9 eğitiminde, temel bir form oluşturmayı, verileri Firebase'e kaydetmeyi ve ondan öğeleri almayı ele aldık.

Yol boyunca, Angular 9 ve Angular Ivy'de hangi iyileştirmelerin ve yeni özelliklerin yer aldığını gördük. Tam bir liste için resmi Angular blogunun en son yayın gönderisine göz atabilirsiniz.


Google Cloud İş Ortağı rozeti.

Bir Google Cloud İş Ortağı olarak, Toptal'ın Google sertifikalı uzmanları, en önemli projeleri için şirketlere talep üzerine hizmet vermektedir.