Karena kami membuat situs yang sangat bergantung pada JavaScript, terkadang kami membayar apa yang kami hasilkan dengan cara yang tidak selalu dapat kami lihat dengan mudah. Dalam artikel ini, kami akan membahas mengapa sedikit disiplin dapat membantu jika Anda ingin situs Anda dimuat dan menjadi interaktif dengan cepat di perangkat seluler. Mengirimkan lebih sedikit JavaScript dapat berarti lebih sedikit waktu dalam transmisi jaringan, lebih sedikit kode dekompresi yang dihabiskan, dan lebih sedikit waktu untuk mem-parsing dan mengompilasi JavaScript ini.
Jaringan
Ketika sebagian besar developer memikirkan biaya JavaScript, mereka memikirkannya dari segi biaya download dan eksekusi. Mengirim lebih banyak byte JavaScript melalui kabel membutuhkan waktu lebih lama, sehingga kecepatan koneksi pengguna menjadi lebih lambat.
Hal ini dapat menjadi masalah, karena jenis koneksi jaringan efektif yang dimiliki pengguna mungkin sebenarnya bukan 3G, 4G, atau Wi-Fi. Anda dapat menggunakan Wi-Fi di kedai kopi, tetapi terhubung ke {i>hotspot<i} seluler dengan kecepatan 2G.
Anda dapat mengurangi biaya transfer jaringan JavaScript melalui:
- Hanya kirimkan kode yang diperlukan pengguna.
- Gunakan pemisahan kode untuk membagi JavaScript Anda menjadi beberapa yang penting dan mana yang tidak. Pemaket modul seperti webpack mendukung pemisahan kode.
- Pemuatan lambat dalam kode yang tidak penting.
- Minifikasi
- Gunakan UglifyJS untuk meminimalkan kode ES5.
- Gunakan babel-minify atau uglify-es untuk meminifikasi ES2015+.
- Kompresi
- Setidaknya, gunakan gzip untuk mengompresi resource berbasis teks.
- Pertimbangkan untuk menggunakan Brotli ~q11. Pada rasio kompresi, Brotli memiliki performa yang lebih baik dibandingkan gzip. Solusi ini membantu CertSimple menghemat 17% ukuran byte JS yang dikompresi, dan LinkedIn menghemat 4% waktu pemuatan.
- Menghapus kode yang tidak digunakan.
- Identifikasi peluang untuk kode yang dapat dihapus atau dimuat dengan lambat dengan cakupan kode DevTools.
- Gunakan babel-preset-env dan browserlist untuk menghindari transpilasi fitur yang sudah ada di browser modern. Developer tingkat lanjut dapat menemukan bahwa analisis paket webpack yang cermat dapat membantu mengidentifikasi peluang untuk memangkas dependensi yang tidak diperlukan.
- Untuk menghapus kode, lihat tree-shaking, plugin pemangkasan library dan pengoptimalan lanjutan Closure Compiler seperti lodash-babel-plugin atau ContextReplacementPlugin webpack untuk library seperti Moment.js.
- Menyimpan kode dalam cache untuk meminimalkan perjalanan jaringan.
- Gunakan cache HTTP untuk memastikan browser merespons cache secara efektif. Tentukan masa aktif optimal untuk skrip (usia maksimum) dan berikan token validasi (ETag) untuk menghindari transfer byte yang tidak berubah.
- Cache Service Worker dapat membuat jaringan aplikasi Anda menjadi lebih tangguh dan memberi Anda akses cepat ke fitur seperti cache kode V8.
- Gunakan penyimpanan cache jangka panjang untuk menghindari keharusan mengambil kembali resource yang belum berubah. Jika menggunakan Webpack, lihat hashing nama file.
Urai/Kompilasi
Setelah didownload, salah satu biaya terberat JavaScript adalah waktu bagi mesin JS untuk mengurai/mengompilasi kode ini. Di Chrome DevTools, parse dan kompilasi adalah bagian dari waktu "Scripting" berwarna kuning di panel Performa.
Tab Bottom-Up dan Call Tree menunjukkan waktu Parse/kompilasi yang tepat:
Namun, mengapa hal ini penting?
Menghabiskan waktu yang lama untuk mengurai/mengompilasi kode dapat sangat memperlambat seberapa cepat pengguna dapat berinteraksi dengan situs Anda. Makin banyak JavaScript yang Anda kirim, makin lama waktu yang diperlukan untuk mengurai dan mengompilasinya sebelum situs Anda menjadi interaktif.
Byte-for-byte, JavaScript lebih mahal untuk diproses oleh browser daripada gambar atau Web Font dengan ukuran yang setara — Tom Dale
Dibandingkan dengan JavaScript, ada banyak biaya yang terlibat dalam pemrosesan gambar yang berukuran setara (masih harus didekode). Namun pada rata-rata hardware seluler, JS lebih cenderung berdampak negatif terhadap interaktivitas halaman.
Ketika berbicara tentang penguraian dan kompilasi yang lambat; konteks itu penting — yang kami maksud adalah rata-rata ponsel di sini. Rata-rata pengguna dapat memiliki ponsel dengan CPU dan GPU lambat, tanpa cache L2/L3, dan yang bahkan mungkin memiliki memori.
Kemampuan jaringan dan kemampuan perangkat tidak selalu cocok. Pengguna dengan koneksi Fiber yang luar biasa tidak selalu memiliki CPU terbaik untuk mengurai dan mengevaluasi JavaScript yang dikirim ke perangkat mereka. Hal ini berlaku untuk kebalikannya... koneksi jaringan yang buruk, tetapi CPU yang luar biasa cepat. — Kristofer Baxter, LinkedIn
Di bawah ini, kita dapat melihat biaya penguraian ~1 MB JavaScript yang didekompresi (sederhana) pada hardware yang rendah dan canggih. Ada perbedaan 2–5x dalam waktu untuk mengurai/mengompilasi kode antara ponsel tercepat di pasar dan ponsel biasa.
Bagaimana dengan situs dunia nyata, seperti CNN.com?
Pada iPhone 8 kelas atas, hanya diperlukan ~4 detik untuk mengurai/mengompilasi JS CNN dibandingkan dengan ~13 detik untuk ponsel rata-rata (Moto G4). Hal ini dapat sangat memengaruhi seberapa cepat pengguna dapat berinteraksi sepenuhnya dengan situs ini.
Hal ini menyoroti pentingnya pengujian pada hardware rata-rata (seperti Moto G4), bukan hanya ponsel yang mungkin berada di saku Anda. Namun, konteks itu penting: optimalkan kondisi perangkat dan jaringan yang dimiliki pengguna Anda.
Apakah kita benar-benar mengeluarkan terlalu banyak JavaScript? Mungkin :)
Dengan menggunakan Arsip HTTP (situs ~500 ribu teratas) untuk menganalisis status JavaScript di seluler, kita dapat melihat bahwa 50% situs memerlukan waktu lebih dari 14 detik untuk interaktif. Situs-situs ini menghabiskan waktu hingga 4 detik hanya untuk mengurai dan mengompilasi JS.
Perhitungkan waktu yang diperlukan untuk mengambil dan memproses JS serta resource lainnya dan mungkin tidak mengejutkan bahwa pengguna dapat menunggu beberapa saat sebelum merasa halaman siap digunakan. Kita pasti dapat melakukan yang lebih baik di sini.
Menghapus JavaScript yang tidak penting dari halaman Anda dapat mengurangi waktu transmisi, penguraian dan kompilasi yang intensif CPU, serta potensi overhead memori. Hal ini juga membantu membuat halaman Anda interaktif dengan lebih cepat.
Waktu eksekusi
Ini bukan hanya penguraian dan kompilasi yang dapat menimbulkan biaya. Eksekusi JavaScript (menjalankan kode setelah diuraikan/dikompilasi) adalah salah satu operasi yang harus terjadi di thread utama. Waktu eksekusi yang lama juga dapat memengaruhi seberapa cepat pengguna dapat berinteraksi dengan situs Anda.
Jika skrip dijalankan selama lebih dari 50 milidetik, waktu interaktif akan tertunda selama seluruh jumlah waktu yang diperlukan untuk mendownload, mengompilasi, dan mengeksekusi JS — Alex Russell
Untuk mengatasinya, JavaScript memanfaatkan potongan kecil untuk menghindari penguncian thread utama. Pelajari apakah Anda dapat mengurangi jumlah pekerjaan yang dilakukan selama eksekusi.
Biaya lain
JavaScript dapat memengaruhi performa halaman dengan cara lain:
- Memori. Halaman dapat terlihat tersendat atau sering dijeda karena GC (pembersihan sampah memori). Saat browser mengklaim kembali memori, eksekusi JS akan dijeda sehingga browser yang sering membersihkan sampah memori dapat menjeda eksekusi lebih sering daripada yang mungkin kita inginkan. Hindari kebocoran memori dan jeda GC yang sering agar halaman tetap bebas jank.
- Selama runtime, JavaScript yang berjalan lama dapat memblokir thread utama yang menyebabkan
halaman tidak responsif. Membagi pekerjaan menjadi potongan-potongan kecil (menggunakan
requestAnimationFrame()
ataurequestIdleCallback()
untuk penjadwalan) dapat meminimalkan masalah responsivitas yang dapat membantu meningkatkan Interaction to Next Paint (INP).
Pola untuk mengurangi biaya pengiriman JavaScript
Saat Anda mencoba untuk mempertahankan waktu penguraian/kompilasi dan waktu pengiriman jaringan untuk JavaScript dengan lambat, ada pola yang dapat membantu seperti pemotongan berbasis rute atau PRPL.
PRPL
PRPL (Push, Render, Pre-cache, Lazy-load) adalah pola yang dioptimalkan untuk interaktivitas melalui pemisahan kode dan cache yang agresif:
Mari kita visualisasikan dampaknya.
Kami menganalisis waktu pemuatan situs seluler populer dan Progressive Web App menggunakan Statistik Panggilan Runtime V8. Seperti yang dapat kita lihat, waktu penguraian (ditampilkan dalam warna oranye) adalah bagian penting dari waktu sebagian besar situs tersebut menghabiskan waktu:
Wego, situs yang menggunakan PRPL, mengelola waktu penguraian yang rendah untuk rute mereka, sehingga mendapatkan interaktif dengan sangat cepat. Banyak situs lain di atas menerapkan anggaran pemisahan kode dan performa untuk mencoba menurunkan biaya JS.
Bootstrap Progresif
Banyak situs mengoptimalkan visibilitas konten dengan interaktivitas yang mahal. Untuk mendapatkan "first paint" yang cepat saat Anda memiliki paket JavaScript yang besar, terkadang developer menggunakan rendering sisi server, lalu "mengupgradenya" untuk menambahkan pengendali peristiwa saat JavaScript akhirnya diambil.
Hati-hati — hal ini memiliki biaya sendiri. Anda 1) umumnya mengirimkan respons HTML lebih besar yang dapat mendorong interaktivitas kami, 2) dapat membuat pengguna berada di lembah aneh, di mana separuh pengalaman tidak dapat benar-benar interaktif hingga JavaScript selesai diproses.
Bootstrap Progresif mungkin merupakan pendekatan yang lebih baik. Kirimkan halaman yang berfungsi secara minimal (yang hanya terdiri dari HTML/JS/CSS yang dibutuhkan untuk rute saat ini). Seiring meningkatnya jumlah resource, aplikasi dapat mengalami pemuatan lambat dan membuka lebih banyak fitur.
Kode pemuatan yang proporsional dengan tampilan adalah objek yang tidak disangka-sangka. PRPL dan {i>Bootstrapping<i} Progresif adalah pola yang dapat membantu mencapai hal ini.
Kesimpulan
Ukuran transmisi sangat penting untuk jaringan kelas bawah. Waktu penguraian penting untuk perangkat yang mengandalkan CPU. Pertahankan tingkat kepercayaan yang rendah ini penting.
Tim telah menemukan keberhasilan dalam mengadopsi anggaran performa yang ketat untuk menjaga agar waktu transmisi JavaScript dan penguraian/kompilasi tetap rendah. Lihat tulisan Alex Russell "Can You Afford It?: Anggaran Performa Web Sesungguhnya" untuk panduan anggaran untuk seluler.
Jika Anda membuat situs yang menargetkan perangkat seluler, lakukan yang terbaik untuk mengembangkan hardware yang representatif, pertahankan waktu penguraian/kompilasi JavaScript Anda tetap rendah, dan gunakan Anggaran Performa untuk memastikan tim Anda dapat memantau biaya JavaScript mereka.
Pelajari Lebih Lanjut
- Chrome Dev Summit 2017 - Praktik Terbaik Pemuatan Modern
- Performa Start-up JavaScript
- Menyelesaikan krisis performa web — Nolan Lawson
- Apakah Anda mampu membayarnya? Anggaran performa dunia nyata — Alex Russell
- Mengevaluasi framework dan library web — Kristofer Baxter
- Hasil eksperimen dengan Brotli dari Cloudflare untuk kompresi (perhatikan bahwa Brotli dinamis dengan kualitas lebih tinggi dapat menunda rendering halaman awal, jadi evaluasilah dengan cermat. Anda mungkin ingin mengompresi secara statis.)
- Masa Depan Performa — Sam Saccone