Tingkatkan kinerja SPA dengan memecah perpustakaan Angular Anda menjadi beberapa bagian

Halo, Habr! Saya mempersembahkan kepada Anda terjemahan artikel “Tingkatkan kinerja SPA dengan membagi perpustakaan Angular Anda menjadi beberapa bagian” oleh Kevin Kreuzer .


Sudut adalah kerangka kerja yang bagus. Kita semua mencintainya <3.


Salah satu hal yang membuat Angular sukses dan cantik pada saat yang sama adalah komunitas luas dan nilai yang dibawanya. Ada banyak pertemuan, blog, konferensi, dan, tentu saja, perpustakaan Angular.


Berkat Angular CLI, perpustakaan mudah dibuat hari ini. Mereka bagus untuk berbagi kode antara beberapa aplikasi.


Karena mereka dapat digunakan di banyak tempat, kinerja adalah aspek penting. Perpustakaan yang kinerjanya buruk dapat memperlambat banyak aplikasi!


Frontend memiliki berbagai jenis kinerja. runtime - kinerja dan beban awal. Pada artikel ini, kami akan fokus pada pemuatan awal.


Dengan menyediakan dan mendukung berbagai pustaka dan kerangka kerja antarmuka pengguna untuk perusahaan besar, saya menemukan beberapa jebakan yang tidak begitu jelas dan cara untuk memperbaikinya. Saya pikir ada baiknya berbagi beberapa dari mereka.


"Ini perpustakaan yang sederhana. Itu tidak bisa memengaruhi kinerja, kan?"


Mari kita mulai dengan perpustakaan sederhana yang akan kita buat menggunakan Angular CLI. Jika Anda belum pernah membuat perpustakaan Angular, mungkin bermanfaat bagi Anda untuk membaca artikel berikut:


gambar


Segera setelah kami menggunakan CLI untuk mengkonfigurasi banyak ruang kerja proyek, kami dapat mulai menambahkan kode.


Perpustakaan disebut howdy dan tujuan utamanya adalah untuk menyambut Anda dengan nama Anda atau memberi tahu Anda waktu setempat. Ini berisi dua modul dengan masing-masing komponen. Satu model menyambut, yang lain berbicara waktu.


gambar


Hanya modul Angular dan Komponen biasa yang mengambil properti nama di atas bindings Input dan menampilkannya.


gambar


HowdyTimeComponent bertanggung jawab untuk menampilkan waktu menggunakan perpustakaan momen pihak ketiga.


Hebat! Perpustakaan howdy kami siap untuk dipublikasikan! Ini adalah perpustakaan yang sederhana; dia tidak akan dapat mempengaruhi kinerja, bukan?


Konsumsi perpustakaan Howdy


Sekarang kami memiliki perpustakaan howdy ! Sayang sekali tidak memanfaatkan ini. Untuk menggunakan perpustakaan howdy , kami membuat SPA baru dengan Angular CLI.


ng new greeting-app 

Karena kami tertarik pada kinerja, mari kita juga menginstal dependensi dev yang disebut webpack-bundle-analyzer .


 npm i -D webpack-bundle-analyzer 

Webpack-bundle-analyzer memungkinkan Anda untuk memvisualisasikan ukuran file output webpack Anda menggunakan peta pohon interaktif yang dapat diskalakan.


Cara terbaik untuk menganalisis paket kami adalah dengan menambahkan skrip analisis berikut ke package.json kami.


 "analyze": "ng build --prod --stats-json && webpack-bundle-analyzer ./dist/greeting-app/stats-es2015.json" 

Jika kita menjalankan perintah ini, Angular akan melakukan build produksi dan juga output stats-es2015.json , yang kemudian akan dipilih dan diberikan oleh webpack-bundle-anlyzer .


gambar


Karena kami belum menulis kode apa pun, paket utama kami sebagian besar terdiri dari Angular. Kita juga dapat melihat bahwa zone.js termasuk dalam paket polyfill kami.


Secara umum, ukuran aplikasi kita sekarang 207 KB .


Tapi kami belum memasukkan perpustakaan Howdy kami! Ayo maju dan lakukan itu.


 npm i howdy 

Kami memasang pustaka howdy karena kami ingin menjadi tuan rumah salam dengan nama. Kami tidak tertarik dengan demonstrasi waktu. Oleh karena itu, kami hanya akan menggunakan modul HowdyNameModule dan tidak akan menyertakan HowdyTimeModule .


gambar


Penting untuk dicatat di sini bahwa kami hanya mengimpor HowdyNameModule . Mari kita jalankan skrip analisis analisis lagi.


gambar


Wow! Sangat keren! Kami beralih dari 207 KB ke 511,15 KB. Ukurannya lebih dari dua kali lipat. Apa ...!


Satu lirikan saja sudah cukup untuk menemukan pelakunya. momen sangat besar! Ini membawa kode implementasi utama dan semua pengaturan regional.


Tentu saja, moment dapat diganti dengan paket lain, seperti date-fns atau moment-mini . Tetapi pertanyaannya berbeda; Kenapa dia ada di sana? Ingat bahwa kami hanya mengimpor HowdyNameModule , bukan HodwyTimeModule . Saya pikir ketika Tree shaking terjadi , hanya modul yang tidak digunakan yang terlepas? Apa yang sedang terjadi


Pohon goyang mungkin tidak menghilangkan semuanya


Agar Pohon bergetar terjadi, bangunan Angular meluncurkan sekelompok optimisasi canggih. Tapi tetap saja, saat ini hadir dalam kit, meskipun HowdyTimeModule tidak.
Masalahnya adalah bagaimana momen itu dikemas. Mari kita cepat melihat file moment.js di folder node_modules kami.


gambar


Karena momen dapat digunakan di banyak tempat, seperti backend Node JS, aplikasi Angular, atau JavaScript biasa, ia dibundel dalam UMD dan bukan sebagai modul ES .


Pustaka UMD yang tertaut dibungkus dalam fungsi IFFE, yang berarti bahwa ModuleConcatenation tidak dapat digunakan. Alat optimisasi perakitan tidak dapat mengetahui apakah kode ini akan digunakan atau jika memiliki efek samping.


Singkatnya, modul jenis ini mencegah Angular meluncurkan kit optimisasi yang lebih canggih.


Sayangnya, kami tidak dapat mengontrol bagaimana momen itu selesai. Apakah ini berarti kita harus tahan dengan ukuran paket yang tipis?


Titik masuk sekunder untuk kemenangan


Kami tidak dapat mengontrol bagaimana momen dibuat. Tetapi kita dapat mengelola perpustakaan kita. Memang, ada cara untuk mencegah skenario seperti itu. Titik masuk sekunder!


Hampir semua perpustakaan Angular saat ini dikemas menggunakan ng-packagr . ng-packagr memungkinkan Anda untuk menggunakan ng-package.json dalam kombinasi dengan public-api , yang pada akhirnya akan menjadi titik masuk ke aplikasi Anda.


Sesuai namanya, titik masuk tambahan memungkinkan Anda menentukan beberapa titik masuk untuk aplikasi Anda.


Kedengarannya bagus! Bagaimana cara mengaktifkan titik masuk sekunder?


Titik masuk sekunder terdeteksi secara dinamis menggunakan ng-packagr . ng-packagr mencari file package.json di subdirektori dari folder utama file package.json


Keren! Mari manfaatkan titik masuk sekunder di pustaka howdy kami dengan menambahkan file berikut.


gambar


Untuk setiap modul, kami menambahkan index.ts , package.json dan public_api.ts .


  • index.ts ada di sana, hanya untuk menunjuk ke public_api , yang berguna selama impor.
  • public_api mengekspor semua modul dan komponen dari modul kami.
  • package.json berisi konfigurasi ng-packagr tertentu . Dalam kasus kami, ini cukup untuk menentukan entryFile .

Package.json juga dapat berisi properti lain, seperti cssUrl , dll. Perhatikan bahwa ruang lingkup properti ini hanya sub-item saat ini.

Jika kita menjalankan perakitan sekarang, kita mendapatkan tiga blok. howdy.js , howdy-src-lib-name.js dan howdy-src-lib-time.js .


Howdy-src-lib-name.js sekarang hanya berisi kode yang terkait dengan HowdyNameModule , dan howdy-src-lib-time.js sekarang hanya berisi kode khusus untuk HowdyTimeModule .


Tapi mari kita lihat sepotong howdy.js .


gambar


Bagian howdy.js masih mengandung HowdyNameComponent dan HowdyTimeComponent . Ini berarti bahwa kami masih mendapatkan momen, bahkan jika kami hanya mengimpor HowdyNameModule .


Jika kita ingin menyingkirkan HowdyTimeModule dengan pendekatan ini, kita perlu menggunakan impor mendalam. Jadi kami mengimpor bukan dari howdy.js , tetapi langsung dari howdy-src-lib-time.js
Apa yang tidak direkomendasikan! Impor dalam sangat berbahaya dan harus selalu dihindari!

Bagaimana kita bisa menyelesaikan masalah ini? Bagaimana kami dapat menjamin bahwa HowdyTimeModule juga akan dihapus bahkan jika kami menggunakan impor standar? Nah, kita perlu mengatur cara untuk membuat sepotong howdy.js .


Gunakan "plang"


Idenya adalah untuk menghapus kode dari blok howdy.js dan sebagai gantinya memungkinkannya untuk bertindak sebagai semacam "penunjuk arah" "pointer" yang mengarahkan Anda ke blok lain.


Jadi mari kita lihat lebih dekat src / public_api.ts .


 /* * Public API Surface of howdy */ export * from './lib/name/howdy-name.component'; export * from './lib/name/howdy-name.module'; export * from './lib/time/howdy-time.component'; export * from './lib/time/howdy-time.module'; 

Baris-baris ini bertanggung jawab untuk memasukkan semuanya dari nama dan waktu di blok howdy.js . Kita perlu menghapus kode dari howdydy.js dan membiarkannya menunjuk ke fragmen lain yang berisi implementasi. Mari kita ubah isinya.


 / * Public API Surface of howdy */ export * from 'howdy/src/lib/name'; export * from 'howdy/src/lib/time'; 

Alih-alih mengekspor implementasi yang sebenarnya, kami menunjukkan jalur relatif ke berbagai bagian. Dengan perubahan ini, howdy.js hanya menunjuk ke paket lain dan tidak mengandung kode "nyata".
Ayo jalankan ng build dan analisis folder dist kami.


gambar


Howdy.js sekarang bertindak sebagai "penunjuk arah" "penunjuk" yang menunjuk ke fragmen yang berisi implementasi. Blok howdy-src-lib-name.js hanya berisi kode dari folder nama , dan file howdy-src-lib-time.js hanya berisi kode dari folder waktu .


Lengkapi paket dengan pengganti


Mari kita perbarui paket howdy dalam aplikasi selamat datang kami dan jalankan kembali skrip analisis.


gambar


Keren Ukuran paket sekarang 170,94 KB . Sedikit lebih tinggi dari aslinya. Mari kita lihat bagaimana modul Howdy terlihat di bundel terakhir.


gambar


Hebat! Penyesuaian ini memungkinkan kami untuk menjaga ukuran paket yang memakan SPA kecil. SPA hanya mendapatkan apa yang mereka butuhkan!


Titik masuk sekunder sangat baik bila Anda menggunakannya bersamaan dengan pemuatan malas. Jika kita menggunakan HowdyTimeModule dalam modul yang malas, momen akan berakhir menjadi bagian malas, dan tidak pada dasarnya.

Pengalaman nyata


Contoh di atas sangat sederhana.


Namun, setelah pengenalan titik masuk sekunder ke proyek perusahaan yang ada, semuanya akan berbeda. Anda harus berurusan dengan kompleksitas yang jauh lebih besar, sementara pesan kesalahan dari ng-packagr tidak selalu berguna.


Kemungkinan besar, Anda perlu mengkonfigurasi beberapa jalur impor atau menentukan beberapa jalur di file tsconfig.json Anda. Dan Anda juga akan menemukan modul dari satu blok yang menggunakan modul dari blok lain.


Tapi percayalah, begitu Anda mengelola beban ini, itu sepadan.


Dalam lingkungan perusahaan yang luas, kami menemukan bahwa ukuran paket SPA yang baru dibuat meledak setelah kami memasukkan beberapa perpustakaan yang kami sediakan.


Pada titik tertentu, bahkan mencapai 5 MB . Setiap SPA menerima momen , @swimlane / datatable, dan hal-hal lain yang bahkan tidak ia gunakan. Kami mulai fokus untuk mengoptimalkan ukuran paket ini.


Kami menghapus momen dari date-fns dan mulai menggunakan titik masuk sekunder. Saat ini, kami telah menerima unit utama 662KB untuk SPA yang baru dibuat, yang mencakup beberapa perpustakaan. Ini masih banyak, tetapi kita belum selesai. Optimalisasi belum selesai - kami dapat mengurangi ukuran paket lebih jauh.


Sangat keren melihat di mana kita berada dan dari mana kita berasal.


Namun, terlepas dari kenyataan bahwa dalam contoh di atas cukup mudah untuk menggunakan titik masuk tambahan, itu bisa sangat sulit untuk membayangkan mereka dalam proyek yang lebih signifikan.


Kesimpulan


Angular melakukan pekerjaan yang baik dalam hal mengoptimalkan ukuran paket. Meskipun langkah-langkah perakitan untuk optimasi sangat kompleks, mereka tidak dapat mengguncang pohon bergetar.


Modul yang dikemas dalam format selain ESModules tidak dapat diguncang pohon.


Oleh karena itu, sebagai pencipta perpustakaan, kita harus hati-hati memantau dampak perpustakaan kita pada ukuran paket ketika kita memasukkan perpustakaan pihak ketiga.
Kami tidak dapat mengontrol pengemasan perpustakaan pihak ketiga. Tapi kami memiliki kontrol yang sangat baik atas pengemasan perpustakaan kami.


Sub-bagian menawarkan kepada kami cara yang bagus untuk mengirimkan perpustakaan kami di beberapa bagian. Potongan-potongan ini dapat dikocok (pohon goyang) selama optimalisasi perakitan Angulars. Dengan pendekatan ini, bahkan pustaka pihak ketiga yang dikemas secara salah dimasukkan dalam paket akhir hanya jika digunakan.

Source: https://habr.com/ru/post/id482646/


All Articles