
Selamat sore, kolega. Kami sedang mempertimbangkan apakah akan memperbarui buku oleh Jacob Fine dan Anton Moiseev "
Angular dan TypeScript. Membangun situs web untuk para profesional ."
Edisi baru keluar musim gugur ini dan mencakup materi tentang Angular 5 dan 6.
Awalnya kami berpikir untuk menerbitkan materi tentang mesin Ivy, yang kemungkinan akan menjadi inovasi paling menarik di Angular 6, tetapi kemudian kami berhenti pada publikasi yang lebih umum dari Cedric Exbright (aslinya dirilis pada Mei).
Di Angular 6, ada banyak inovasi serius, apalagi, yang paling penting dari mereka Anda tidak dapat menyebutkan fitur: ini Ivy, mesin render baru. Karena mesin ini masih eksperimental, kami akan membicarakannya di akhir artikel ini, dan mulai dengan fitur baru dan perubahan revolusioner lainnya.
Penyedia yang bisa digerakkan pohonSekarang ada cara baru yang disarankan untuk mendaftarkan penyedia secara langsung di dekorator
@Injectable()
, menggunakan atribut baru yang
providedIn
. Dibutuhkan
'root'
sebagai nilai modul apa pun dalam aplikasi Anda. Saat menggunakan
'root'
objek yang diimplementasikan akan didaftarkan dalam aplikasi sebagai penyendiri, dan Anda tidak perlu menambahkannya ke penyedia di modul root. Demikian pula, ketika menggunakan
providedIn: UsersModule
objek yang diimplementasikan terdaftar sebagai penyedia
UsersModule
, dan tidak ditambahkan ke penyedia modul.
@Injectable({ providedIn: 'root' }) export class UserService { }
Metode baru seperti itu diperkenalkan untuk menghapus kode non-fungsional dengan lebih baik dalam aplikasi (tree-shaking). Saat ini, situasinya sedemikian rupa sehingga layanan yang ditambahkan ke penyedia modul akan berakhir pada set terakhir, bahkan jika itu tidak digunakan dalam aplikasi - dan membiarkan ini sedikit sedih. Jika Anda menggunakan lazy loading, Anda dapat jatuh ke dalam beberapa perangkap sekaligus, atau menemukan diri Anda dalam situasi di mana layanan akan dimasukkan dalam rangkaian yang salah.
Situasi seperti itu dalam aplikasi tidak mungkin sering terjadi (jika Anda menulis layanan, lalu menggunakannya), tetapi modul pihak ketiga terkadang menawarkan layanan yang tidak kita butuhkan - sebagai hasilnya, kita memiliki sejumlah besar JavaScript yang tidak berguna.
Jadi, fitur ini akan sangat berguna bagi pengembang perpustakaan, tetapi sekarang dianjurkan untuk mendaftarkan objek yang diimplementasikan dengan cara ini - ini juga berlaku untuk pengembang aplikasi. CLI baru sekarang bahkan menggunakan scaffolding yang
providedIn: 'root'
secara default ketika bekerja dengan layanan.
Dengan nada yang sama, Anda sekarang dapat mendeklarasikan
InjectionToken
, mendaftarkannya langsung dengan yang
providedIn
dan menambahkan
factory
sini:
export const baseUrl = new InjectionToken<string>('baseUrl', { providedIn: 'root', factory: () => 'http://localhost:8080/' });
Harap dicatat: ini juga menyederhanakan pengujian unit. Untuk keperluan pengujian semacam itu, mereka digunakan untuk mendaftarkan layanan dengan penyedia modul uji. Inilah yang kami lakukan sebelumnya:
beforeEach(() => TestBed.configureTestingModule({ providers: [UserService] }));
Sekarang, jika Layanan Pengguna menggunakan
providedIn: 'root'
:
beforeEach(() => TestBed.configureTestingModule({}));
Hanya saja, jangan khawatir: semua layanan yang terdaftar dengan In tidak dimasukkan ke dalam tes, tetapi malas dipakai, hanya dalam kasus ketika mereka benar-benar diperlukan.
Rxjs 6Angular 6 sekarang menggunakan RxJS 6 secara internal, jadi Anda perlu memperbarui aplikasi dengan mempertimbangkan hal ini.
Dan ... RxJS 6 mengubah pendekatan untuk mengimpor!
Di RxJS 5, Anda bisa menulis:
import { Observable } from 'rxjs/Observable'; import 'rxjs/add/observable/of'; import 'rxjs/add/operator/map'; const squares$: Observable<number> = Observable.of(1, 2) .map(n => n * n);
Dalam RxJS 5.5, pernyataan yang dapat disambungkan muncul:
import { Observable } from 'rxjs/Observable'; import { of } from 'rxjs/observable/of'; import { map } from 'rxjs/operators'; const squares$: Observable<number> = of(1, 2).pipe( map(n => n * n) );
Dan di RxJS 6.0, impor telah berubah:
import { Observable, of } from 'rxjs'; import { map } from 'rxjs/operators'; const squares$: Observable<number> = of(1, 2).pipe( map(n => n * n) );
Jadi, suatu hari Anda harus mengubah impor dalam seluruh aplikasi. Saya menulis "sekali", dan bukan "sekarang", karena perpustakaan rxJs-compat dirilis di RxJS, yang memungkinkan mengunduh RxJS ke versi 6.0, bahkan jika versi lama masih digunakan di seluruh aplikasi Anda atau di salah satu perpustakaan yang digunakan sintaksis.
Tim Angular telah menulis
seluruh dokumen tentang hal ini, dan mutlak diperlukan untuk membacanya sebelum bermigrasi ke Angular 6.0.
Harap dicatat: di sini adalah seperangkat aturan tslint yang sangat keren yang disebut
rxjs-tslint
. Hanya ada 4 aturan di dalamnya, dan jika Anda menambahkannya ke proyek, sistem akan secara otomatis memigrasi semua impor dan kode RxJS Anda, dan ini dilakukan oleh
tslint --fix
! Lagi pula, jika Anda masih belum tahu, di
tslint
ada opsi
fix
yang secara otomatis memperbaiki semua kesalahan yang ditemukannya! Ini dapat digunakan lebih sederhana lagi: instal
rxjs-tslint
secara global dan jalankan
rxjs-5-to-6-migrate -p src/tsconfig.app.json
. Saya mencoba
rxjs-tslint
di salah satu proyek kami dan itu bekerja dengan cukup baik (jalankan setidaknya dua kali untuk juga menutup semua impor). Lihat README dari proyek ini untuk lebih jelasnya:
github.com/ReactiveX/rxjs-tslint .
Jika Anda tertarik untuk mempelajari lebih lanjut tentang RxJS 6.0, saya merekomendasikan
laporan Ben Lesch
berikutnya tentang ng-conf.
i18nProspek terpenting yang terkait dengan i18n adalah kemampuan untuk membuat "i18n saat runtime", tanpa harus membuat aplikasi secara terpisah untuk setiap titik lokal. Fitur ini belum tersedia (hanya ada prototipe), dan mesin Ivy akan diperlukan untuk operasinya (lebih lanjut tentang itu di bawah).
Perubahan lain terkait i18n telah terjadi dan tersedia. Saluran mata uang dioptimalkan dengan cara yang paling efisien: sekarang ia membulatkan semua mata uang tidak menjadi 2 digit, seperti sebelumnya, tetapi ke jumlah digit yang diinginkan (misalnya, ke 3 dalam kasus dinar Bahrain atau ke 0 untuk peso Chili).
Jika diperlukan, nilai ini dapat diambil secara terprogram menggunakan fungsi
getNumberOfCurrencyDigits
i18n baru.
Fungsi pemformatan nyaman lainnya, seperti
formatDate
,
formatCurrency
,
formatPercent
dan
formatNumber
juga muncul di
formatNumber
formatPercent
.
Cukup nyaman, jika Anda ingin menerapkan transformasi yang sama yang dilakukan di saluran, tetapi lakukan dari kode TypeScript.
AnimasiDi Angular 6.0, animasi sudah dimungkinkan tanpa polyfill
web-animations-js
, kecuali Anda menggunakan
AnimationBuilder
. Aplikasi Anda dapat memenangkan beberapa byte berharga! Jika browser tidak mendukung API
element.animate
, Angular 6.0 memutar kembali ke penggunaan kerangka kunci CSS.
Elemen SudutAngular Elements adalah proyek yang memungkinkan Anda untuk membungkus komponen Angular sebagai komponen web dan menyematkannya dalam aplikasi yang tidak menggunakan Angular. Pada awalnya, proyek ini hanya ada di "Angular Lab" (artinya, masih eksperimental). Dengan v6, ia muncul sedikit di garis depan dan secara resmi dimasukkan dalam kerangka kerja. Ini adalah topik besar yang layak mendapat artikel terpisah.
ElementRef <T>Jika Anda ingin mengambil tautan elemen dalam templat Anda, Anda bisa menggunakan
@ViewChild
atau
@ViewChildren
, atau bahkan langsung mengimplementasikan
ElementRef
. Kekurangan dalam hal ini adalah ini: dalam Angular 5.0 atau lebih rendah,
ElementRef
ditentukan akan mendapatkan jenis
any
untuk properti
nativeElement
.
Di Angular 6.0 Anda bisa mengetik ElementRef lebih ketat jika Anda mau:
@ViewChild('loginInput') loginInput: ElementRef<HTMLInputElement>; ngAfterViewInit() {
Apa yang diakui sebagai yang tidak diinginkan dan apa yang berubah secara fundamentalMari kita bicara tentang apa yang perlu Anda ingat ketika memulai migrasi!
preserveWhitespaces
: default false
Di bagian "Masalah yang mungkin terjadi selama pemutakhiran", kami mencatat bahwa preserveWhitespaces sekarang
false
secara default. Opsi ini muncul di Angular 4.4, dan jika Anda bertanya-tanya apa yang diharapkan pada saat yang sama - di sini adalah
seluruh posting tentang topik ini. Spoiler: semuanya bisa dilakukan, atau sepenuhnya dapat merusak templat Anda.
ngModel
dan formulir reaktifSebelumnya, dimungkinkan untuk menyediakan bidang formulir yang sama dengan
ngModel
dan
formControl
, tetapi hari ini praktik ini dianggap tidak diinginkan dan tidak akan lagi didukung dalam Angular 7.0.
Ada sedikit kebingungan di sini, dan seluruh mekanisme bekerja, mungkin tidak seperti yang Anda harapkan (
ngModel
- ini adalah arahan yang belum lama Anda kenal, tetapi input / output dari direktif
formControl
, yang melakukan hampir sama, tetapi bukan tugas yang identik).
Jadi sekarang, jika kita menerapkan kode:
<input [(ngModel)]="user.name" [formControl]="nameCtrl">
maka kita mendapat peringatan.
Anda dapat mengkonfigurasi aplikasi untuk menampilkan peringatan
always
(
once
),
once
(sekali) atau
never
(tidak pernah). Default
always
.
imports: [ ReactiveFormsModule.withConfig({ warnOnNgModelWithFormControl: 'never' }); ]
Dengan satu atau lain cara, mempersiapkan transisi ke Angular 7, Anda perlu menyesuaikan kode untuk menggunakan formulir berorientasi template atau formulir reaktif.
Proyek Ivy: mesin render baru (baru) di AngularSoooo ... Ini adalah rilis Angular utama ke-4 (2, 4, 5, 6), dan mesin rendering sedang ditulis ulang untuk ketiga kalinya!
Ingat: Angular mengkompilasi template Anda menjadi kode TypeScript yang setara. Kemudian TypeScript ini dikompilasi dengan TypeScript yang Anda tulis dalam JavaScript, dan hasilnya ada di tangan pengguna. Dan sebelum kita sudah versi ke-3 dari mesin rendering ini di Angular (yang pertama adalah dalam rilis awal Angular 2.0, dan yang kedua di Angular 4.0).
Dalam versi baru dari mesin render ini, pendekatan penulisan templat tidak berubah, namun, ia mengoptimalkan sejumlah indikator, khususnya:
Semua ini masih sangat eksperimental, dan mesin rendering Ivy baru dihidupkan oleh kotak centang, yang harus Anda masukkan ke dalam opsi kompiler (dalam file
tsconfig.json
) jika Anda ingin mencobanya.
"angularCompilerOptions": { "enableIvy": true }
Harap dicatat bahwa mekanisme ini mungkin tidak terlalu dapat diandalkan, jadi jangan menggunakannya dalam produksi. Mungkin dia masih tidak bekerja. Tetapi dalam waktu dekat ini akan diterima sebagai opsi default, jadi Anda harus mencobanya sekali, lihat apakah itu berfungsi di aplikasi Anda, dan apa yang Anda manfaatkan darinya.
Mari kita bahas secara lebih rinci perbedaan Ivy dari mesin rendering yang lebih lama.
Kode yang dihasilkan oleh mesin lamaMari kita
PonyComponent
contoh kecil: mari kita memiliki komponen
PonyComponent
yang mengambil model
PonyModel
(dengan parameter
name
dan
color
) dan menampilkan gambar kuda poni (tergantung pada setelannya), serta nama kuda poni.
Ini terlihat seperti ini:
@Component({ selector: 'ns-pony', template: `<div> <ns-image [src]="getPonyImageUrl()"></ns-image> <div></div> </div>` }) export class PonyComponent { @Input() ponyModel: PonyModel; getPonyImageUrl() { return `images/${this.ponyModel.color}.png`; } }
Mesin rendering yang diperkenalkan pada Angular 4 menghasilkan kelas yang disebut
ngfactory
untuk setiap templat. Kelas biasanya berisi (kode disederhanakan):
export function View_PonyComponent_0() { return viewDef(0, [ elementDef(0, 0, null, null, 4, "div"), elementDef(1, 0, null, null, 1, "ns-image", View_ImageComponent_0), directiveDef(2, 49152, null, 0, i2.ImageComponent, { src: [0, "src"] }), elementDef(3, 0, null, null, 1, "div"), elementDef(4, null, ["", ""]) ], function (check, view) { var component = view.component; var currVal_0 = component.getPonyImageUrl(); check(view, 2, 0, currVal_0); }, function (check, view) { var component = view.component; var currVal_1 = component.ponyModel.name; check(view, 4, 0, currVal_1); }); }
Sulit dibaca, tetapi bagian utama dari kode ini dijelaskan sebagai berikut:
- Struktur DOM yang dibuat, yang berisi definisi elemen (
figure
, img
, figcaption
), atribut dan definisi node teks. Setiap elemen struktur DOM dalam array definisi tampilan diwakili oleh indeksnya sendiri. - Ubah fungsi deteksi; kode yang terkandung di dalamnya memeriksa untuk melihat apakah ekspresi yang digunakan dalam templat menghasilkan nilai yang sama seperti sebelumnya. Di sini, hasil dari metode
getPonyImageUrl
dan, jika berubah, nilai input untuk komponen gambar diperbarui. Hal yang sama berlaku untuk nama panggilan pony: jika berubah, simpul teks yang berisi nama panggilan ini akan diperbarui.
Ivy menghasilkan kodeJika kita bekerja dengan Angular 6, dan flag
enableIvy
disetel ke
true
, maka pabrik terpisah tidak akan dihasilkan dalam contoh yang sama; Informasi akan tertanam langsung ke bidang statis komponen itu sendiri (kode yang disederhanakan):
export class PonyComponent { static ngComponentDef = defineComponent({ type: PonyComponent, selector: [['ns-pony']], factory: () => new PonyComponent(), template: (renderFlag, component) { if (renderFlag & RenderFlags.Create) { elementStart(0, 'figure'); elementStart(1, 'ns-image'); elementEnd(); elementStart(2, 'div'); text(3); elementEnd(); elementEnd(); } if (renderFlag & RenderFlags.Update) { property(1, 'src', component.getPonyImageUrl()); text(3, interpolate('', component.ponyModel.name, '')); } }, inputs: { ponyModel: 'ponyModel' }, directives: () => [ImageComponent]; });
Sekarang semuanya terkandung dalam bidang statis ini. Atribut
template
berisi yang setara dengan
ngfactory
sudah
ngfactory
, dengan struktur yang sedikit berbeda. Fungsi
template
, seperti sebelumnya, akan diluncurkan pada setiap perubahan, tetapi sekarang ia memiliki dua mode:
- Mode kreasi: komponen baru saja dibuat, ini berisi node DOM statis yang perlu dibuat
- Sisa fungsi dijalankan dengan setiap perubahan (jika perlu, memperbarui sumber gambar dan simpul teks).
Apa yang berubah?Sekarang semua dekorator dibangun langsung ke dalam kelas mereka (sama untuk
@Injectable
,
@Pipe
,
@Directive
), dan untuk menghasilkannya Anda hanya perlu tahu tentang dekorator saat ini. Fenomena ini disebut oleh tim Angular sebagai "prinsip lokalitas": untuk mengkompilasi ulang komponen, Anda tidak perlu menganalisis ulang aplikasi.
Kode yang dihasilkan sedikit berkurang, tetapi yang lebih penting, adalah mungkin untuk menghilangkan sejumlah dependensi, sehingga mempercepat kompilasi ulang jika salah satu bagian dari aplikasi berubah. Selain itu, dengan kolektor modern, misalnya, Webpack, semuanya ternyata jauh lebih cantik: kode non-fungsional terputus dengan aman, bagian-bagian kerangka kerja yang tidak Anda gunakan. Misalnya, jika Anda tidak memiliki saluran dalam aplikasi, maka kerangka kerja yang diperlukan untuk interpretasinya bahkan tidak termasuk dalam set terakhir.
Kami terbiasa membuat kode Angular berat. Kadang tidak menakutkan, tetapi Hello World dengan berat 37 kb setelah minifikasi dan kompresi terlalu banyak. Ketika Ivy bertanggung jawab untuk menghasilkan kode, kode non-fungsional terputus jauh lebih efisien. Sekarang Hello World setelah minifikasi dikompresi menjadi 7,3 kb, dan setelah kompresi - hanya 2,7 kb, dan ini adalah perbedaan besar. Aplikasi TodoMVC setelah kompresi - hanya 12,2 kb. Ini adalah data dari tim Angular, dan yang lain tidak bisa bekerja bersama kami, karena untuk Ivy bekerja seperti yang dijelaskan di sini, Anda masih perlu menambalnya secara manual.
Untuk lebih jelasnya, lihat
pembicaraan ini dengan ng-conf.
Kompatibilitas dengan perpustakaan yang adaAnda mungkin tertarik pada: apa yang akan terjadi pada perpustakaan yang sudah diterbitkan dalam format lama jika Ivy digunakan dalam proyek Anda? Jangan khawatir: mesin akan membuat versi dependensi proyek Anda yang kompatibel dengan Ivy, bahkan jika mereka dikompilasi tanpa Ivy. Saya tidak akan mengekspos interior sekarang, tetapi semua detail harus transparan.
Fitur baruMari kita pertimbangkan peluang baru apa yang akan kita miliki ketika bekerja dengan mesin layar ini.
Properti pribadi di templatMesin baru menambahkan fitur baru atau perubahan potensial.
Situasi ini terkait langsung dengan fakta bahwa fungsi templat tertanam dalam bidang statis komponen: sekarang kita dapat menggunakan properti pribadi komponen kita di templat. Ini sebelumnya tidak mungkin, karena itu kami dipaksa untuk mempublikasikan semua bidang dan metode komponen yang digunakan dalam templat, dan mereka jatuh ke kelas yang terpisah (
ngfactory
). Saat mengakses properti pribadi dari kelas lain, kompilasi TypeScript akan gagal. Sekarang sudah ada di masa lalu: karena fungsi templat berada di bidang statis, ia memiliki akses ke properti pribadi komponen.
Saya melihat komentar dari anggota tim Angular tentang fakta bahwa tidak disarankan untuk menggunakan properti pribadi dalam templat, meskipun sekarang mungkin - karena mungkin dilarang lagi di masa depan ... karena itu, mungkin lebih bijaksana untuk terus menggunakan hanya bidang publik dalam templat! Bagaimanapun, penulisan unit test sekarang lebih mudah, karena tes dapat memeriksa keadaan komponen tanpa membuat dan memeriksa DOM untuk ini.
i18n saat runtimeHarap dicatat: mesin rendering baru akhirnya membuka peluang yang sudah lama ditunggu-tunggu bagi kami dan memberikan "i18n saat runtime". Pada saat penulisan, dia masih belum siap, tetapi kami melihat beberapa komitmen sekaligus, dan ini adalah pertanda baik!
Yang keren adalah Anda tidak perlu banyak mengubah aplikasi jika Anda sudah bekerja dengan i18n. Tetapi sekarang Anda tidak perlu membangun kembali aplikasi untuk setiap lokal yang Anda rencanakan untuk dukung - cukup unggah JSON dengan terjemahan untuk setiap lokal, dan Angular akan mengurus sisanya!
Perpustakaan AoTSaat ini, perpustakaan yang dirilis di NPM harus menerbitkan file metadata.json dan tidak dapat menerbitkan kode AoT dari komponen-komponennya. Ini menyedihkan, karena biaya yang terkait dengan perakitan seperti itu diteruskan ke aplikasi kita. Dengan Ivy, tidak perlu untuk file metadata, dan penulis perpustakaan sekarang akan dapat mempublikasikan kode AoT mereka langsung ke NPM!
Track stack yang ditingkatkanSekarang kode yang dihasilkan harus memberikan jejak tumpukan ditingkatkan, jika Anda mendapatkan masalah dengan template Anda - menghasilkan kesalahan rapi yang menunjukkan garis templat di mana itu terjadi. Anda bahkan dapat mengatur breakpoint di templat dan melacak apa yang sebenarnya terjadi di Angular.
NgModule
menghilang?Ini masih merupakan prospek yang jauh, tetapi mungkin di masa depan akan mungkin dilakukan tanpa NgModules. Tanda-tanda pertama dari perubahan tersebut adalah penyedia pohon-goyang, dan logis untuk mengasumsikan bahwa Ivy memiliki semua blok dasar yang diperlukan bagi mereka yang siap untuk secara bertahap meninggalkan NgModules (atau, setidaknya, membuat mereka kurang responsif). Benar, semua ini masih di masa depan, kita akan bersabar.
Tidak akan ada banyak fitur baru dalam rilis ini, tetapi Ivy jelas menarik untuk masa depan. Percobaan dengan itu - Saya ingin tahu bagaimana Anda akan menyukainya!