Daftar Periksa Kinerja Front-End 2021 (PDF, Apple Pages, MS Word)
Diterbitkan: 2022-03-10Panduan ini telah didukung dengan baik oleh teman-teman kami di LogRocket, layanan yang menggabungkan pemantauan kinerja frontend , pemutaran ulang sesi, dan analisis produk untuk membantu Anda membangun pengalaman pelanggan yang lebih baik. LogRocket melacak metrik utama, termasuk. DOM selesai, waktu untuk byte pertama, penundaan input pertama, CPU klien dan penggunaan memori. Dapatkan uji coba gratis LogRocket hari ini.
Kinerja web adalah binatang yang rumit, bukan? Bagaimana kita benar-benar tahu di mana kita berdiri dalam hal kinerja, dan apa sebenarnya hambatan kinerja kita? Apakah itu JavaScript yang mahal, pengiriman font web yang lambat, gambar yang berat, atau rendering yang lamban? Sudahkah kita cukup mengoptimalkan dengan pengocokan pohon, pengangkatan ruang lingkup, pemecahan kode, dan semua pola pemuatan mewah dengan pengamat persimpangan, hidrasi progresif, petunjuk klien, HTTP/3, pekerja layanan, dan — oh my — pekerja tepi? Dan, yang paling penting, dari mana kita mulai meningkatkan kinerja dan bagaimana kita membangun budaya kinerja jangka panjang?
Kembali pada hari itu, kinerja sering kali hanya menjadi renungan belaka. Seringkali ditangguhkan hingga akhir proyek, itu akan bermuara pada minifikasi, penggabungan, pengoptimalan aset, dan kemungkinan beberapa penyesuaian halus pada file config
server. Melihat ke belakang sekarang, hal-hal tampaknya telah berubah cukup signifikan.
Performa bukan hanya masalah teknis: performa memengaruhi segalanya mulai dari aksesibilitas hingga kegunaan hingga pengoptimalan mesin telusur, dan saat memasukkannya ke dalam alur kerja, keputusan desain harus diinformasikan oleh implikasi performanya. Kinerja harus diukur, dipantau, dan disempurnakan secara terus-menerus , dan kompleksitas web yang berkembang menimbulkan tantangan baru yang mempersulit pelacakan metrik, karena data akan sangat bervariasi tergantung pada perangkat, browser, protokol, jenis jaringan, dan latensi ( CDN, ISP, cache, proxy, firewall, penyeimbang beban, dan server semuanya berperan dalam kinerja).
Jadi, jika kami membuat ikhtisar tentang semua hal yang harus kami ingat saat meningkatkan kinerja — dari awal proyek hingga rilis akhir situs web — seperti apa tampilannya? Di bawah ini Anda akan menemukan daftar periksa kinerja front-end (semoga tidak bias dan objektif) untuk tahun 2021 — tinjauan umum terbaru tentang masalah yang mungkin perlu Anda pertimbangkan untuk memastikan bahwa waktu respons Anda cepat, interaksi pengguna lancar, dan situs Anda tidak menguras bandwidth pengguna.
Daftar isi
- Semua di halaman terpisah
- Persiapan: Perencanaan Dan Metrik
Budaya kinerja, Data Web Inti, profil kinerja, CrUX, Mercusuar, FID, TTI, CLS, perangkat. - Menetapkan Tujuan yang Realistis
Anggaran kinerja, sasaran kinerja, kerangka kerja RAIL, anggaran 170KB/30KB. - Mendefinisikan Lingkungan
Memilih kerangka kerja, biaya kinerja dasar, Webpack, dependensi, CDN, arsitektur front-end, CSR, SSR, CSR + SSR, rendering statis, prarendering, pola PRPL. - Pengoptimalan Aset
Brotli, AVIF, WebP, gambar responsif, AV1, pemuatan media adaptif, kompresi video, font web, font Google. - Membangun Optimasi
Modul JavaScript, pola modul/nomodul, perombakan pohon, pemecahan kode, peningkatan cakupan, Webpack, penyajian diferensial, pekerja web, WebAssembly, bundel JavaScript, Bereaksi, SPA, hidrasi parsial, impor pada interaksi, pihak ketiga, cache. - Pengoptimalan Pengiriman
Pemuatan lambat, pengamat persimpangan, penundaan rendering dan decoding, CSS penting, streaming, petunjuk sumber daya, perubahan tata letak, pekerja layanan. - Jaringan, HTTP/2, HTTP/3
Stapel OCSP, sertifikat EV/DV, pengemasan, IPv6, QUIC, HTTP/3. - Pengujian Dan Pemantauan
Alur kerja audit, browser proxy, halaman 404, permintaan izin cookie GDPR, CSS diagnostik kinerja, aksesibilitas. - Kemenangan Cepat
- Unduh Daftar Periksa (PDF, Halaman Apple, MS Word)
- Ayo kita pergi!
(Anda juga dapat mengunduh PDF daftar periksa (166 KB) atau mengunduh file Apple Pages (275 KB) yang dapat diedit atau file .docx (151 KB). Selamat mengoptimalkan, semuanya!)
Persiapan: Perencanaan Dan Metrik
Pengoptimalan mikro sangat bagus untuk menjaga kinerja tetap pada jalurnya, tetapi penting untuk memiliki target yang jelas dalam pikiran — sasaran terukur yang akan memengaruhi keputusan apa pun yang dibuat selama proses. Ada beberapa model yang berbeda, dan yang dibahas di bawah ini cukup beropini — pastikan untuk menetapkan prioritas Anda sendiri sejak dini.
- Membangun budaya kinerja.
Di banyak organisasi, pengembang front-end tahu persis apa masalah mendasar yang umum dan strategi apa yang harus digunakan untuk memperbaikinya. Namun, selama tidak ada dukungan yang mapan terhadap budaya kinerja, setiap keputusan akan berubah menjadi medan pertempuran departemen, memecah organisasi menjadi silo. Anda memerlukan dukungan pemangku kepentingan bisnis, dan untuk mendapatkannya, Anda perlu membuat studi kasus, atau bukti konsep tentang bagaimana kecepatan — terutama Data Web Inti yang akan kita bahas nanti secara rinci — metrik manfaat dan Indikator Kinerja Utama ( KPI ) yang mereka pedulikan.Misalnya, untuk membuat kinerja lebih nyata, Anda dapat mengekspos dampak kinerja pendapatan dengan menunjukkan korelasi antara rasio konversi dan waktu untuk memuat aplikasi, serta kinerja rendering. Atau tingkat perayapan bot pencarian (PDF, halaman 27–50).
Tanpa keselarasan yang kuat antara tim pengembang/desain dan bisnis/pemasaran, kinerja tidak akan bertahan dalam jangka panjang. Pelajari keluhan umum yang masuk ke layanan pelanggan dan tim penjualan, pelajari analitik untuk rasio pentalan tinggi dan penurunan konversi. Jelajahi bagaimana meningkatkan kinerja dapat membantu meringankan beberapa masalah umum ini. Sesuaikan argumen tergantung pada kelompok pemangku kepentingan yang Anda ajak bicara.
Jalankan eksperimen kinerja dan ukur hasil — baik di seluler maupun di desktop (misalnya, dengan Google Analytics). Ini akan membantu Anda membangun studi kasus yang disesuaikan dengan perusahaan dengan data nyata. Selain itu, menggunakan data dari studi kasus dan eksperimen yang dipublikasikan di WPO Stats akan membantu meningkatkan sensitivitas bisnis tentang mengapa kinerja penting, dan apa dampaknya terhadap pengalaman pengguna dan metrik bisnis. Menyatakan bahwa kinerja penting saja tidak cukup — Anda juga perlu menetapkan beberapa tujuan yang terukur dan dapat dilacak dan mengamatinya dari waktu ke waktu.
Bagaimana menuju ke sana? Dalam ceramahnya tentang Membangun Kinerja untuk Jangka Panjang, Allison McKnight berbagi studi kasus yang komprehensif tentang bagaimana dia membantu membangun budaya kinerja di Etsy (slide). Baru-baru ini, Tammy Everts telah berbicara tentang kebiasaan tim kinerja yang sangat efektif baik di organisasi kecil maupun besar.
Saat melakukan percakapan ini dalam organisasi, penting untuk diingat bahwa sama seperti UX adalah spektrum pengalaman, kinerja web adalah distribusi. Seperti yang dicatat oleh Karolina Szczur, "mengharapkan satu nomor untuk dapat memberikan peringkat yang diinginkan adalah asumsi yang salah." Oleh karena itu, sasaran kinerja harus terperinci, dapat dilacak, dan nyata.
- Sasaran: Jadilah setidaknya 20% lebih cepat dari pesaing tercepat Anda.
Menurut penelitian psikologis, jika Anda ingin pengguna merasa bahwa situs web Anda lebih cepat daripada situs web pesaing Anda, Anda harus setidaknya 20% lebih cepat. Pelajari pesaing utama Anda, kumpulkan metrik tentang kinerja mereka di seluler dan desktop, dan tetapkan ambang batas yang akan membantu Anda melampaui mereka. Namun, untuk mendapatkan hasil dan sasaran yang akurat, pastikan untuk terlebih dahulu mendapatkan gambaran menyeluruh tentang pengalaman pengguna Anda dengan mempelajari analitik Anda. Anda kemudian dapat meniru pengalaman persentil ke-90 untuk pengujian.Untuk mendapatkan kesan pertama yang baik tentang kinerja pesaing Anda, Anda dapat menggunakan Chrome UX Report ( CrUX , kumpulan data RUM siap pakai, pengenalan video oleh Ilya Grigorik dan panduan terperinci oleh Rick Viscomi), atau Treo, alat pemantauan RUM yang didukung oleh Laporan UX Chrome. Data dikumpulkan dari pengguna browser Chrome, sehingga laporannya akan spesifik untuk Chrome, tetapi laporan tersebut akan memberi Anda distribusi kinerja yang cukup menyeluruh, yang terpenting, skor Core Web Vitals, di berbagai pengunjung Anda. Perhatikan bahwa kumpulan data CrUX baru dirilis pada hari Selasa kedua setiap bulan .
Atau, Anda juga dapat menggunakan:
- Alat Perbandingan Laporan Chrome UX Addy Osmani,
- Speed Scorecard (juga menyediakan penaksir dampak pendapatan),
- Perbandingan Uji Pengalaman Pengguna Nyata atau
- SiteSpeed CI (berdasarkan pengujian sintetis).
Catatan : Jika Anda menggunakan Page Speed Insights atau Page Speed Insights API (tidak, itu tidak ditinggalkan!), Anda bisa mendapatkan data kinerja CrUX untuk halaman tertentu, bukan hanya agregat. Data ini bisa jauh lebih berguna untuk menetapkan target kinerja untuk aset seperti "halaman arahan" atau "daftar produk". Dan jika Anda menggunakan CI untuk menguji anggaran, Anda perlu memastikan lingkungan pengujian Anda cocok dengan CrUX jika Anda menggunakan CrUX untuk menetapkan target ( terima kasih Patrick Meenan! ).
Jika Anda memerlukan bantuan untuk menunjukkan alasan di balik prioritas kecepatan, atau Anda ingin memvisualisasikan penurunan rasio konversi atau peningkatan rasio pentalan dengan kinerja yang lebih lambat, atau mungkin Anda perlu mengadvokasi solusi RUM di organisasi Anda, Sergey Chernyshev telah membangun Kalkulator Kecepatan UX, alat sumber terbuka yang membantu Anda mensimulasikan data dan memvisualisasikannya untuk mengarahkan poin Anda.
Terkadang Anda mungkin ingin sedikit lebih dalam, menggabungkan data yang berasal dari CrUX dengan data lain yang sudah Anda miliki untuk bekerja dengan cepat di mana letak perlambatan, titik buta, dan inefisiensi — untuk pesaing Anda, atau untuk proyek Anda. Dalam karyanya, Harry Roberts telah menggunakan Spreadsheet Topografi Kecepatan Situs yang ia gunakan untuk mengelompokkan kinerja menurut jenis halaman utama, dan melacak perbedaan metrik utama di antara mereka. Anda dapat mengunduh spreadsheet sebagai Google Spreadsheet, Excel, dokumen OpenOffice, atau CSV.
Dan jika Anda ingin melakukannya sepenuhnya , Anda dapat menjalankan audit kinerja Lighthouse di setiap halaman situs (melalui Parade Lightouse), dengan output yang disimpan sebagai CSV. Itu akan membantu Anda mengidentifikasi halaman (atau jenis halaman) spesifik mana dari pesaing Anda yang berkinerja lebih buruk atau lebih baik, dan apa yang mungkin ingin Anda fokuskan pada upaya Anda. (Untuk situs Anda sendiri, mungkin lebih baik mengirim data ke titik akhir analitik!).
Kumpulkan data, siapkan spreadsheet, kurangi 20%, dan atur sasaran Anda ( anggaran kinerja ) dengan cara ini. Sekarang Anda memiliki sesuatu yang terukur untuk diuji. Jika Anda mempertimbangkan anggaran dan mencoba mengirimkan hanya muatan minimal untuk mendapatkan waktu-untuk-interaktif yang cepat, maka Anda berada di jalur yang masuk akal.
Butuh sumber daya untuk memulai?
- Addy Osmani telah menulis artikel yang sangat mendetail tentang cara memulai penganggaran kinerja, cara menghitung dampak fitur baru, dan mulai dari mana saat Anda kelebihan anggaran.
- Panduan Lara Hogan tentang cara mendekati desain dengan anggaran kinerja dapat memberikan petunjuk yang bermanfaat bagi desainer.
- Harry Roberts telah menerbitkan panduan tentang menyiapkan Google Sheet untuk menampilkan dampak skrip pihak ketiga pada kinerja, menggunakan Peta Permintaan,
- Kalkulator Anggaran Kinerja Jonathan Fielding, Kalkulator anggaran-perf Katie Hempenius, dan Kalori Peramban dapat membantu dalam membuat anggaran (terima kasih kepada Karolina Szczur atas perhatiannya).
- Di banyak perusahaan, anggaran kinerja tidak boleh aspiratif, melainkan pragmatis, berfungsi sebagai tanda pegangan untuk menghindari tergelincir melewati titik tertentu. Dalam hal ini, Anda dapat memilih titik data terburuk Anda dalam dua minggu terakhir sebagai ambang batas, dan mengambilnya dari sana. Anggaran Kinerja, Secara pragmatis menunjukkan kepada Anda strategi untuk mencapainya.
- Selain itu, buat anggaran kinerja dan kinerja saat ini terlihat dengan menyiapkan dasbor dengan ukuran pembuatan pelaporan grafik. Ada banyak alat yang memungkinkan Anda untuk mencapainya: Dasbor SiteSpeed.io (sumber terbuka), SpeedCurve dan Kaliber hanyalah beberapa di antaranya, dan Anda dapat menemukan lebih banyak alat di perf.rocks.
Setelah Anda memiliki anggaran, gabungkan anggaran tersebut ke dalam proses pembuatan Anda dengan Webpack Performance Hints and Bundlesize, Lighthouse CI, PWMetrics, atau Sitespeed CI untuk menerapkan anggaran pada pull request dan memberikan riwayat skor dalam komentar PR.
Untuk memaparkan anggaran kinerja ke seluruh tim, integrasikan anggaran kinerja di Lighthouse melalui Lightwallet atau gunakan LHCI Action untuk integrasi Github Actions dengan cepat. Dan jika Anda membutuhkan sesuatu yang khusus, Anda dapat menggunakan pagestest-charts-api, API titik akhir untuk membuat bagan dari hasil WebPagetest.
Kesadaran kinerja seharusnya tidak datang dari anggaran kinerja saja. Sama seperti Pinterest, Anda dapat membuat aturan eslint khusus yang melarang pengimporan dari file dan direktori yang dikenal sangat ketergantungan dan akan membuat bundelnya membengkak. Siapkan daftar paket "aman" yang dapat dibagikan ke seluruh tim.
Juga, pikirkan tentang tugas pelanggan penting yang paling bermanfaat bagi bisnis Anda. Pelajari, diskusikan, dan tentukan ambang waktu yang dapat diterima untuk tindakan kritis dan buat tanda waktu pengguna "siap UX" yang telah disetujui oleh seluruh organisasi. Dalam banyak kasus, perjalanan pengguna akan menyentuh pekerjaan banyak departemen yang berbeda, jadi penyelarasan dalam hal pengaturan waktu yang dapat diterima akan membantu mendukung atau mencegah diskusi kinerja di kemudian hari. Pastikan bahwa biaya tambahan untuk sumber daya dan fitur tambahan terlihat dan dipahami.
Sejajarkan upaya kinerja dengan inisiatif teknologi lainnya, mulai dari fitur baru produk yang sedang dibangun hingga pemfaktoran ulang hingga menjangkau audiens global baru. Jadi setiap kali percakapan tentang pengembangan lebih lanjut terjadi, kinerja juga merupakan bagian dari percakapan itu. Jauh lebih mudah untuk mencapai sasaran kinerja saat basis kode baru atau baru saja difaktorkan ulang.
Juga, seperti yang disarankan Patrick Meenan, ada baiknya merencanakan urutan pemuatan dan pertukaran selama proses desain. Jika Anda memprioritaskan lebih awal bagian mana yang lebih kritis, dan menentukan urutan kemunculannya, Anda juga akan tahu apa yang bisa ditunda. Idealnya, urutan itu juga akan mencerminkan urutan impor CSS dan JavaScript Anda, sehingga menanganinya selama proses pembuatan akan lebih mudah. Juga, pertimbangkan pengalaman visual apa yang seharusnya berada dalam status "di antara", saat halaman sedang dimuat (mis. ketika font web belum dimuat).
Setelah Anda membangun budaya kinerja yang kuat di organisasi Anda, bertujuan untuk menjadi 20% lebih cepat dari diri Anda sebelumnya untuk menjaga prioritas dengan bijaksana seiring berjalannya waktu ( terima kasih, Guy Podjarny! ). Namun, perhitungkan berbagai jenis dan perilaku penggunaan pelanggan Anda (yang oleh Tobias Baldauf disebut irama dan kohort), bersama dengan lalu lintas bot dan efek musiman.
Perencanaan, perencanaan, perencanaan. Mungkin tergoda untuk melakukan beberapa pengoptimalan "bergantung rendah" cepat sejak dini — dan itu mungkin strategi yang baik untuk kemenangan cepat — tetapi akan sangat sulit untuk menjaga kinerja sebagai prioritas tanpa perencanaan dan pengaturan yang realistis, perusahaan -tujuan kinerja yang disesuaikan.
- Pilih metrik yang tepat.
Tidak semua metrik sama pentingnya. Pelajari metrik yang paling penting bagi aplikasi Anda: biasanya, metrik ini akan ditentukan oleh seberapa cepat Anda dapat mulai merender piksel paling penting dari antarmuka Anda dan seberapa cepat Anda dapat memberikan respons input untuk piksel yang dirender ini. Pengetahuan ini akan memberi Anda target pengoptimalan terbaik untuk upaya berkelanjutan. Pada akhirnya, bukan peristiwa pemuatan atau waktu respons server yang menentukan pengalaman, tetapi persepsi tentang seberapa tajam antarmuka itu terasa .Apa artinya? Daripada berfokus pada waktu pemuatan halaman penuh (melalui pengaturan waktu onLoad dan DOMContentLoaded , misalnya), prioritaskan pemuatan halaman seperti yang dirasakan oleh pelanggan Anda. Itu berarti berfokus pada kumpulan metrik yang sedikit berbeda. Faktanya, memilih metrik yang tepat adalah proses tanpa pemenang yang jelas.
Berdasarkan penelitian Tim Kadlec dan catatan Marcos Iglesias dalam ceramahnya, metrik tradisional dapat dikelompokkan menjadi beberapa set. Biasanya, kami membutuhkan semuanya untuk mendapatkan gambaran kinerja yang lengkap, dan dalam kasus khusus Anda, beberapa di antaranya akan lebih penting daripada yang lain.
- Metrik berbasis kuantitas mengukur jumlah permintaan, bobot, dan skor performa. Baik untuk meningkatkan alarm dan memantau perubahan dari waktu ke waktu, tidak begitu baik untuk memahami pengalaman pengguna.
- Metrik tonggak sejarah menggunakan status selama masa proses pemuatan, misalnya Time To First Byte dan Time To Interactive . Baik untuk menggambarkan pengalaman pengguna dan pemantauan, tidak begitu baik untuk mengetahui apa yang terjadi di antara pencapaian.
- Metrik rendering memberikan perkiraan seberapa cepat konten dirender (mis. Waktu Mulai Render , Indeks Kecepatan ). Baik untuk mengukur dan mengubah kinerja rendering, tetapi tidak begitu baik untuk mengukur kapan konten penting muncul dan dapat berinteraksi.
- Metrik khusus mengukur peristiwa khusus tertentu bagi pengguna, misalnya Time To First Tweet dari Twitter dan PinnerWaitTime Pinterest. Baik untuk menggambarkan pengalaman pengguna dengan tepat, tidak begitu baik untuk menskalakan metrik dan membandingkan dengan pesaing.
Untuk melengkapi gambarannya, kami biasanya mencari metrik yang berguna di antara semua grup ini. Biasanya, yang paling spesifik dan relevan adalah:
- Waktu untuk Interaktif (TTI)
Titik di mana tata letak telah stabil , font web utama terlihat, dan utas utama cukup tersedia untuk menangani input pengguna — pada dasarnya tanda waktu ketika pengguna dapat berinteraksi dengan UI. Metrik utama untuk memahami berapa lama waktu yang harus dialami pengguna untuk menggunakan situs tanpa jeda. Boris Schapira telah menulis posting terperinci tentang cara mengukur TTI dengan andal. - Penundaan Input Pertama (FID) , atau Responsivitas input
Waktu dari saat pengguna pertama kali berinteraksi dengan situs Anda hingga saat browser benar-benar dapat merespons interaksi tersebut. Melengkapi TTI dengan sangat baik karena menggambarkan bagian gambar yang hilang: apa yang terjadi ketika pengguna benar-benar berinteraksi dengan situs. Ditujukan sebagai metrik RUM saja. Ada perpustakaan JavaScript untuk mengukur FID di browser. - Cat Contentful Terbesar (LCP)
Menandai titik di garis waktu pemuatan halaman saat konten penting halaman kemungkinan telah dimuat. Asumsinya adalah bahwa elemen halaman yang paling penting adalah yang terbesar yang terlihat di viewport pengguna. Jika elemen dirender di paruh atas dan bawah, hanya bagian yang terlihat yang dianggap relevan. - Total Waktu Pemblokiran ( TBT )
Metrik yang membantu mengukur tingkat keparahan seberapa non-interaktif suatu halaman sebelum menjadi interaktif yang andal (yaitu, utas utama telah bebas dari tugas apa pun yang berjalan lebih dari 50 md ( tugas lama ) setidaknya selama 5 d). Metrik mengukur jumlah total waktu antara pengecatan pertama dan Time to Interactive (TTI) di mana utas utama diblokir cukup lama untuk mencegah respons input. Maka, tidak heran jika TBT yang rendah merupakan indikator yang baik untuk kinerja yang baik. (terima kasih, Artem, Phil) - Pergeseran Tata Letak Kumulatif ( CLS )
Metrik menyoroti seberapa sering pengguna mengalami perubahan tata letak yang tidak terduga ( reflow ) saat mengakses situs. Ini memeriksa elemen yang tidak stabil dan dampaknya terhadap keseluruhan pengalaman. Semakin rendah skornya, semakin baik. - Indeks Kecepatan
Mengukur seberapa cepat konten halaman diisi secara visual; semakin rendah skornya, semakin baik. Skor Indeks Kecepatan dihitung berdasarkan kecepatan kemajuan visual , tetapi itu hanyalah nilai yang dihitung. Ini juga sensitif terhadap ukuran area pandang, jadi Anda perlu menentukan berbagai konfigurasi pengujian yang cocok dengan audiens target Anda. Perhatikan bahwa menjadi kurang penting dengan LCP menjadi metrik yang lebih relevan ( terima kasih, Boris, Artem! ). - Waktu CPU yang dihabiskan
Metrik yang menunjukkan seberapa sering dan berapa lama utas utama diblokir, mengerjakan lukisan, rendering, skrip, dan pemuatan. Waktu CPU yang tinggi merupakan indikator yang jelas dari pengalaman tersendat , yaitu ketika pengguna mengalami jeda yang nyata antara tindakan dan respons mereka. Dengan WebPageTest, Anda dapat memilih "Capture Dev Tools Timeline" pada tab "Chrome" untuk mengekspos perincian utas utama saat berjalan di perangkat apa pun yang menggunakan WebPageTest. - Biaya CPU Tingkat Komponen
Sama seperti waktu CPU yang dihabiskan , metrik ini, yang diusulkan oleh Stoyan Stefanov, mengeksplorasi dampak JavaScript pada CPU . Idenya adalah menggunakan jumlah instruksi CPU per komponen untuk memahami dampaknya pada keseluruhan pengalaman, secara terpisah. Bisa diimplementasikan menggunakan Dalang dan Chrome. - Indeks Frustrasi
Sementara banyak metrik yang ditampilkan di atas menjelaskan kapan peristiwa tertentu terjadi, FrustrationIndex Tim Vereecke melihat kesenjangan di antara metrik alih-alih melihatnya satu per satu. Itu terlihat pada tonggak penting yang dirasakan oleh pengguna akhir, seperti Judul terlihat, Konten pertama terlihat, Siap secara visual dan Halaman terlihat siap dan menghitung skor yang menunjukkan tingkat frustrasi saat memuat halaman. Semakin besar celahnya, semakin besar kemungkinan pengguna merasa frustrasi. Berpotensi KPI yang baik untuk pengalaman pengguna. Tim telah menerbitkan posting terperinci tentang FrustrationIndex dan cara kerjanya. - Dampak Berat Iklan
Jika situs Anda bergantung pada pendapatan yang dihasilkan oleh iklan, akan berguna untuk melacak bobot kode terkait iklan. Skrip Paddy Ganti membuat dua URL (satu normal dan satu memblokir iklan), meminta pembuatan perbandingan video melalui WebPageTest dan melaporkan delta. - Metrik penyimpangan
Sebagaimana dicatat oleh para insinyur Wikipedia, data tentang seberapa banyak perbedaan yang ada dalam hasil Anda dapat memberi tahu Anda seberapa andal instrumen Anda, dan seberapa besar perhatian yang harus Anda berikan pada penyimpangan dan penyimpangan. Varians yang besar merupakan indikator penyesuaian yang diperlukan dalam pengaturan. Ini juga membantu memahami jika halaman tertentu lebih sulit diukur dengan andal, misalnya karena skrip pihak ketiga menyebabkan variasi yang signifikan. Mungkin juga merupakan ide yang baik untuk melacak versi browser untuk memahami peningkatan kinerja saat versi browser baru diluncurkan. - Metrik khusus
Metrik khusus ditentukan oleh kebutuhan bisnis dan pengalaman pelanggan Anda. Ini mengharuskan Anda untuk mengidentifikasi piksel penting , skrip penting , CSS yang diperlukan , dan aset yang relevan , serta mengukur seberapa cepat mereka dikirim ke pengguna. Untuk itu, Anda dapat memantau Waktu Rendering Pahlawan, atau menggunakan Performance API, menandai stempel waktu tertentu untuk acara yang penting bagi bisnis Anda. Selain itu, Anda dapat mengumpulkan metrik khusus dengan WebPagetest dengan mengeksekusi JavaScript arbitrer di akhir pengujian.
Perhatikan bahwa First Meaningful Paint (FMP) tidak muncul dalam ikhtisar di atas. Ini digunakan untuk memberikan wawasan tentang seberapa cepat server mengeluarkan data apa pun . FMP panjang biasanya menunjukkan JavaScript memblokir utas utama, tetapi bisa juga terkait dengan masalah back-end/server. Namun, metrik tersebut telah ditinggalkan baru-baru ini karena tampaknya tidak akurat pada sekitar 20% kasus. Itu secara efektif diganti dengan LCP yang lebih andal dan lebih mudah untuk dipikirkan. Itu tidak lagi didukung di Lighthouse. Periksa kembali metrik dan rekomendasi kinerja yang berpusat pada pengguna terbaru hanya untuk memastikan Anda berada di halaman aman ( terima kasih, Patrick Meenan ).
Steve Souders memiliki penjelasan rinci tentang banyak metrik ini. Penting untuk diperhatikan bahwa meskipun Time-To-Interactive diukur dengan menjalankan audit otomatis dalam apa yang disebut lingkungan lab , First Input Delay mewakili pengalaman pengguna yang sebenarnya , dengan pengguna yang sebenarnya mengalami kelambatan yang nyata. Secara umum, mungkin ide yang baik untuk selalu mengukur dan melacak keduanya.
Bergantung pada konteks aplikasi Anda, metrik pilihan mungkin berbeda: misalnya untuk Netflix TV UI, respons input kunci, penggunaan memori, dan TTI lebih penting, dan untuk Wikipedia, perubahan visual pertama/terakhir dan metrik waktu CPU yang dihabiskan lebih penting.
Catatan : FID dan TTI tidak memperhitungkan perilaku pengguliran; pengguliran dapat terjadi secara independen karena di luar utas utama, jadi untuk banyak situs konsumsi konten, metrik ini mungkin jauh kurang penting ( terima kasih, Patrick! ).
- Ukur dan optimalkan Core Web Vitals .
Untuk waktu yang lama, metrik kinerja cukup teknis, dengan fokus pada tampilan teknik tentang seberapa cepat server merespons, dan seberapa cepat browser memuat. Metrik telah berubah selama bertahun-tahun — mencoba menemukan cara untuk menangkap pengalaman pengguna yang sebenarnya , daripada pengaturan waktu server. Pada Mei 2020, Google telah mengumumkan Core Web Vitals, serangkaian metrik kinerja baru yang berfokus pada pengguna, masing-masing mewakili aspek berbeda dari pengalaman pengguna.Untuk masing-masing dari mereka, Google merekomendasikan berbagai sasaran kecepatan yang dapat diterima. Setidaknya 75% dari semua tampilan halaman harus melebihi rentang Baik untuk lulus penilaian ini. Metrik ini dengan cepat mendapatkan daya tarik, dan dengan Data Web Inti menjadi sinyal peringkat untuk Google Penelusuran pada Mei 2021 ( pembaruan algoritme peringkat Pengalaman Halaman ), banyak perusahaan telah mengalihkan perhatian mereka ke skor kinerja mereka.
Mari kita uraikan setiap Data Web Inti, satu per satu, bersama dengan teknik dan alat yang berguna untuk mengoptimalkan pengalaman Anda dengan mempertimbangkan metrik ini. (Perlu dicatat bahwa Anda akan mendapatkan skor Core Web Vitals yang lebih baik dengan mengikuti saran umum dalam artikel ini.)
- Cat Contentful Terbesar ( LCP ) < 2.5 dtk.
Mengukur pemuatan halaman, dan melaporkan waktu render dari gambar atau blok teks terbesar yang terlihat dalam area pandang. Oleh karena itu, LCP dipengaruhi oleh semua yang menunda rendering informasi penting — baik itu waktu respons server yang lambat, memblokir CSS, JavaScript dalam penerbangan (pihak pertama atau pihak ketiga), pemuatan font web, operasi rendering atau pengecatan yang mahal, malas gambar -loaded, layar kerangka atau rendering sisi klien.
Untuk pengalaman yang baik, LCP harus muncul dalam 2,5 detik sejak halaman pertama kali mulai dimuat. Itu berarti kita perlu merender bagian halaman pertama yang terlihat sedini mungkin. Itu akan membutuhkan CSS penting yang disesuaikan untuk setiap template, mengatur<head>
-order dan mengambil aset penting terlebih dahulu (kita akan membahasnya nanti).Alasan utama untuk skor LCP yang rendah biasanya adalah gambar. Untuk menghadirkan LCP dalam <2,5 detik pada Fast 3G — dihosting di server yang dioptimalkan dengan baik, semua statis tanpa rendering sisi klien dan dengan gambar yang berasal dari CDN gambar khusus — berarti ukuran gambar teoritis maksimum hanya sekitar 144 KB . Itulah mengapa gambar responsif penting, serta memuat gambar penting lebih awal (dengan
preload
).Kiat cepat : untuk menemukan apa yang dianggap LCP pada halaman, di DevTools Anda dapat mengarahkan kursor ke lencana LCP di bawah "Waktu" di Panel Kinerja ( terima kasih, Tim Kadlec !).
- Penundaan Input Pertama ( FID ) < 100 ms.
Mengukur responsivitas UI, yaitu berapa lama browser sibuk dengan tugas lain sebelum dapat bereaksi terhadap peristiwa masukan pengguna yang berbeda seperti ketukan, atau klik. Ini dirancang untuk menangkap penundaan yang dihasilkan dari utas utama yang sibuk, terutama selama pemuatan halaman.
Tujuannya adalah untuk tetap berada dalam jarak 50–100 md untuk setiap interaksi. Untuk sampai ke sana, kita perlu mengidentifikasi tugas yang panjang (memblokir utas utama selama >50 md) dan memecahnya, membagi kode bundel menjadi beberapa bagian, mengurangi waktu eksekusi JavaScript, mengoptimalkan pengambilan data, menunda eksekusi skrip pihak ketiga , pindahkan JavaScript ke utas latar belakang dengan pekerja Web dan gunakan hidrasi progresif untuk mengurangi biaya rehidrasi di SPA.Kiat cepat : secara umum, strategi yang andal untuk mendapatkan skor FID yang lebih baik adalah meminimalkan pekerjaan pada utas utama dengan memecah bundel yang lebih besar menjadi yang lebih kecil dan melayani apa yang dibutuhkan pengguna saat mereka membutuhkannya, sehingga interaksi pengguna tidak akan tertunda . Kami akan membahas lebih lanjut tentang itu secara rinci di bawah ini.
- Pergeseran Tata Letak Kumulatif ( CLS ) < 0,1.
Mengukur stabilitas visual UI untuk memastikan interaksi yang mulus dan alami, yaitu jumlah total semua skor pergeseran tata letak individual untuk setiap perubahan tata letak tak terduga yang terjadi selama masa aktif halaman. Pergeseran tata letak individual terjadi setiap kali elemen yang sudah terlihat mengubah posisinya di halaman. Ini dinilai berdasarkan ukuran konten dan jarak perpindahannya.
Jadi setiap kali pergeseran muncul — misalnya ketika font cadangan dan font web memiliki metrik font yang berbeda, atau iklan, penyematan, atau iframe datang terlambat, atau dimensi gambar/video tidak dicadangkan, atau CSS yang terlambat memaksa pengecatan ulang, atau perubahan disuntikkan oleh JavaScript terlambat — ini berdampak pada skor CLS. Nilai yang direkomendasikan untuk pengalaman yang baik adalah CLS <0,1.
Perlu dicatat bahwa Data Web Inti diharapkan berkembang dari waktu ke waktu, dengan siklus tahunan yang dapat diprediksi . Untuk pembaruan tahun pertama, kami mungkin mengharapkan First Contentful Paint dipromosikan ke Core Web Vitals, ambang batas FID yang dikurangi, dan dukungan yang lebih baik untuk aplikasi satu halaman. We might also see the responding to user inputs after load gaining more weight, along with security, privacy and accessibility (!) considerations.
Related to Core Web Vitals, there are plenty of useful resources and articles that are worth looking into:
- Web Vitals Leaderboard allows you to compare your scores against competition on mobile, tablet, desktop, and on 3G and 4G.
- Core SERP Vitals, a Chrome extension that shows the Core Web Vitals from CrUX in the Google Search Results.
- Layout Shift GIF Generator that visualizes CLS with a simple GIF (also available from the command line).
- web-vitals library can collect and send Core Web Vitals to Google Analytics, Google Tag Manager or any other analytics endpoint.
- Analyzing Web Vitals with WebPageTest, in which Patrick Meenan explores how WebPageTest exposes data about Core Web Vitals.
- Optimizing with Core Web Vitals, a 50-min video with Addy Osmani, in which he highlights how to improve Core Web Vitals in an eCommerce case-study.
- Cumulative Layout Shift in Practice and Cumulative Layout Shift in the Real World are comprehensive articles by Nic Jansma, which cover pretty much everything about CLS and how it correlates with key metrics such as Bounce Rate, Session Time or Rage Clicks.
- What Forces Reflow, with an overview of properties or methods, when requested/called in JavaScript, that will trigger the browser to synchronously calculate the style and layout.
- CSS Triggers shows which CSS properties trigger Layout, Paint and Composite.
- Fixing Layout Instability is a walkthrough of using WebPageTest to identify and fix layout instability issues.
- Cumulative Layout Shift, The Layout Instability Metric, another very detailed guide by Boris Schapira on CLS, how it's calcualted, how to measure and how to optimize for it.
- How To Improve Core Web Vitals, a detailed guide by Simon Hearne on each of the metrics (including other Web Vitals, such as FCP, TTI, TBT), when they occur and how they are measured.
So, are Core Web Vitals the ultimate metrics to follow ? Tidak terlalu. They are indeed exposed in most RUM solutions and platforms already, including Cloudflare, Treo, SpeedCurve, Calibre, WebPageTest (in the filmstrip view already), Newrelic, Shopify, Next.js, all Google tools (PageSpeed Insights, Lighthouse + CI, Search Console etc.) and many others.
However, as Katie Sylor-Miller explains, some of the main problems with Core Web Vitals are the lack of cross-browser support, we don't really measure the full lifecycle of a user's experience, plus it's difficult to correlate changes in FID and CLS with business outcomes.
As we should be expecting Core Web Vitals to evolve, it seems only reasonable to always combine Web Vitals with your custom-tailored metrics to get a better understanding of where you stand in terms of performance.
- Cat Contentful Terbesar ( LCP ) < 2.5 dtk.
- Gather data on a device representative of your audience.
To gather accurate data, we need to thoroughly choose devices to test on. In most companies, that means looking into analytics and creating user profiles based on most common device types. Yet often, analytics alone doesn't provide a complete picture. A significant portion of the target audience might be abandoning the site (and not returning back) just because their experience is too slow, and their devices are unlikely to show up as the most popular devices in analytics for that reason. So, additionally conducting research on common devices in your target group might be a good idea.Globally in 2020, according to the IDC, 84.8% of all shipped mobile phones are Android devices. An average consumer upgrades their phone every 2 years, and in the US phone replacement cycle is 33 months. Average bestselling phones around the world will cost under $200.
A representative device, then, is an Android device that is at least 24 months old , costing $200 or less, running on slow 3G, 400ms RTT and 400kbps transfer, just to be slightly more pessimistic. This might be very different for your company, of course, but that's a close enough approximation of a majority of customers out there. In fact, it might be a good idea to look into current Amazon Best Sellers for your target market. ( Thanks to Tim Kadlec, Henri Helvetica and Alex Russell for the pointers! ).
What test devices to choose then? The ones that fit well with the profile outlined above. It's a good option to choose a slightly older Moto G4/G5 Plus, a mid-range Samsung device (Galaxy A50, S8), a good middle-of-the-road device like a Nexus 5X, Xiaomi Mi A3 or Xiaomi Redmi Note 7 and a slow device like Alcatel 1X or Cubot X19, perhaps in an open device lab. For testing on slower thermal-throttled devices, you could also get a Nexus 4, which costs just around $100.
Also, check the chipsets used in each device and do not over-represent one chipset : a few generations of Snapdragon and Apple as well as low-end Rockchip, Mediatek would be enough (thanks, Patrick!) .
If you don't have a device at hand, emulate mobile experience on desktop by testing on a throttled 3G network (eg 300ms RTT, 1.6 Mbps down, 0.8 Mbps up) with a throttled CPU (5× slowdown). Eventually switch over to regular 3G, slow 4G (eg 170ms RTT, 9 Mbps down, 9Mbps up), and Wi-Fi. To make the performance impact more visible, you could even introduce 2G Tuesdays or set up a throttled 3G/4G network in your office for faster testing.
Keep in mind that on a mobile device, we should be expecting a 4×–5× slowdown compared to desktop machines. Mobile devices have different GPUs, CPU, memory and different battery characteristics. That's why it's important to have a good profile of an average device and always test on such a device.
- Synthetic testing tools collect lab data in a reproducible environment with predefined device and network settings (eg Lighthouse , Calibre , WebPageTest ) and
- Real User Monitoring ( RUM ) tools evaluate user interactions continuously and collect field data (eg SpeedCurve , New Relic — the tools provide synthetic testing, too).
- use Lighthouse CI to track Lighthouse scores over time (it's quite impressive),
- run Lighthouse in GitHub Actions to get a Lighthouse report alongside every PR,
- run a Lighthouse performance audit on every page of a site (via Lightouse Parade), with an output saved as CSV,
- use Lighthouse Scores Calculator and Lighthouse metric weights if you need to dive into more detail.
- Lighthouse is available for Firefox as well, but under the hood it uses the PageSpeed Insights API and generates a report based on a headless Chrome 79 User-Agent.
Luckily, there are many great options that help you automate the collection of data and measure how your website performs over time according to these metrics. Keep in mind that a good performance picture covers a set of performance metrics, lab data and field data:
The former is particularly useful during development as it will help you identify, isolate and fix performance issues while working on the product. The latter is useful for long-term maintenance as it will help you understand your performance bottlenecks as they are happening live — when users actually access the site.
By tapping into built-in RUM APIs such as Navigation Timing, Resource Timing, Paint Timing, Long Tasks, etc., synthetic testing tools and RUM together provide a complete picture of performance in your application. You could use Calibre, Treo, SpeedCurve, mPulse and Boomerang, Sitespeed.io, which all are great options for performance monitoring. Furthermore, with Server Timing header, you could even monitor back-end and front-end performance all in one place.
Note : It's always a safer bet to choose network-level throttlers, external to the browser, as, for example, DevTools has issues interacting with HTTP/2 push, due to the way it's implemented ( thanks, Yoav, Patrick !). For Mac OS, we can use Network Link Conditioner, for Windows Windows Traffic Shaper, for Linux netem, and for FreeBSD dummynet.
As it's likely that you'll be testing in Lighthouse, keep in mind that you can:
- Set up "clean" and "customer" profiles for testing.
While running tests in passive monitoring tools, it's a common strategy to turn off anti-virus and background CPU tasks, remove background bandwidth transfers and test with a clean user profile without browser extensions to avoid skewed results (in Firefox, and in Chrome).However, it's also a good idea to study which browser extensions your customers use frequently, and test with dedicated "customer" profiles as well. In fact, some extensions might have a profound performance impact (2020 Chrome Extension Performance Report) on your application, and if your users use them a lot, you might want to account for it up front. Hence, "clean" profile results alone are overly optimistic and can be crushed in real-life scenarios.
- Bagikan sasaran kinerja dengan rekan kerja Anda.
Pastikan bahwa sasaran kinerja diketahui oleh setiap anggota tim Anda untuk menghindari kesalahpahaman di kemudian hari. Setiap keputusan — baik itu desain, pemasaran, atau apa pun di antaranya — memiliki implikasi kinerja , dan mendistribusikan tanggung jawab dan kepemilikan di seluruh tim akan menyederhanakan keputusan yang berfokus pada kinerja di kemudian hari. Memetakan keputusan desain terhadap anggaran kinerja dan prioritas yang ditentukan sejak awal.
Menetapkan Tujuan yang Realistis
- Waktu respons 100 milidetik, 60 fps.
Agar interaksi terasa mulus, antarmuka memiliki 100 ms untuk merespons masukan pengguna. Lebih lama dari itu, dan pengguna menganggap aplikasi itu lamban. RAIL, model kinerja yang berpusat pada pengguna memberi Anda target yang sehat : Untuk memungkinkan respons <100 milidetik, halaman harus mengembalikan kontrol ke utas utama paling lambat setelah setiap <50 milidetik. Perkiraan Latensi Input memberi tahu kita jika kita mencapai ambang itu, dan idealnya, itu harus di bawah 50 md. Untuk titik-titik bertekanan tinggi seperti animasi, yang terbaik adalah tidak melakukan hal lain di mana Anda bisa dan minimum absolut di mana Anda tidak bisa.Selain itu, setiap bingkai animasi harus diselesaikan dalam waktu kurang dari 16 milidetik, sehingga mencapai 60 bingkai per detik (1 detik 60 = 16,6 milidetik) — sebaiknya di bawah 10 milidetik. Karena browser membutuhkan waktu untuk melukis bingkai baru ke layar, kode Anda harus selesai dieksekusi sebelum mencapai tanda 16,6 milidetik. Kami mulai berdiskusi tentang 120fps (misalnya layar iPad Pro berjalan pada 120Hz) dan Surma telah membahas beberapa solusi kinerja rendering untuk 120fps, tapi itu mungkin bukan target yang kami lihat dulu .
Jadilah pesimis dalam ekspektasi kinerja, tetapi optimis dalam desain antarmuka dan gunakan waktu idle dengan bijak (periksa idle, idle-sampai-mendesak dan react-idle). Jelas, target ini berlaku untuk kinerja waktu proses, bukan kinerja pemuatan.
- FID < 100 md, LCP < 2.5 d, TTI < 5 d pada 3G, Anggaran ukuran file penting < 170KB (gzip).
Meskipun mungkin sangat sulit untuk dicapai, tujuan akhir yang baik adalah Waktu untuk Interaktif di bawah 5 detik, dan untuk kunjungan berulang, bidik di bawah 2 detik (hanya dapat dicapai dengan pekerja layanan). Bertujuan untuk Cat Isi Terbesar di bawah 2,5 detik dan meminimalkan Waktu Pemblokiran Total dan Pergeseran Tata Letak Kumulatif . Penundaan Input Pertama yang dapat diterima adalah di bawah 100 md–70 md. Seperti disebutkan di atas, kami mempertimbangkan baseline sebagai ponsel Android seharga $200 (misalnya Moto G4) pada jaringan 3G yang lambat, diemulasi pada 400ms RTT dan kecepatan transfer 400kbps.Kami memiliki dua kendala utama yang secara efektif membentuk target yang masuk akal untuk pengiriman konten yang cepat di web. Di satu sisi, kami memiliki kendala pengiriman jaringan karena TCP Mulai Lambat. 14KB pertama dari HTML — 10 paket TCP, masing-masing 1460 byte, menghasilkan sekitar 14,25 KB, meskipun tidak diartikan secara harfiah — adalah bagian muatan yang paling penting, dan satu-satunya bagian dari anggaran yang dapat dikirimkan dalam perjalanan pulang pergi pertama ( hanya itu yang Anda dapatkan dalam 1 detik pada 400ms RTT karena waktu bangun seluler).
( Catatan : karena TCP umumnya kurang memanfaatkan koneksi jaringan dalam jumlah yang signifikan, Google telah mengembangkan TCP Bottleneck Bandwidth dan RRT ( BBR ), sebuah algoritma kontrol aliran TCP yang dikendalikan penundaan TCP. Dirancang untuk web modern, ia merespons kemacetan yang sebenarnya, daripada kehilangan paket seperti TCP, ini jauh lebih cepat, dengan throughput yang lebih tinggi dan latensi yang lebih rendah — dan algoritme bekerja secara berbeda. ( terima kasih, Victor, Barry! )
Di sisi lain, kami memiliki kendala perangkat keras pada memori dan CPU karena penguraian JavaScript dan waktu eksekusi (kami akan membicarakannya secara rinci nanti). Untuk mencapai tujuan yang dinyatakan dalam paragraf pertama, kita harus mempertimbangkan anggaran ukuran file penting untuk JavaScript. Pendapat bervariasi tentang berapa anggaran yang seharusnya (dan itu sangat tergantung pada sifat proyek Anda), tetapi anggaran 170KB JavaScript yang sudah di-gzip akan membutuhkan waktu hingga 1 detik untuk diurai dan dikompilasi pada ponsel kelas menengah. Dengan asumsi bahwa 170KB berkembang menjadi 3x ukuran itu ketika didekompresi (0,7MB), itu sudah bisa menjadi lonceng kematian dari pengalaman pengguna yang "layak" di Moto G4/G5 Plus.
Dalam kasus situs web Wikipedia, pada tahun 2020, secara global, eksekusi kode menjadi 19% lebih cepat untuk pengguna Wikipedia. Jadi, jika metrik kinerja web Anda dari tahun ke tahun tetap stabil, itu biasanya merupakan tanda peringatan karena Anda sebenarnya mengalami kemunduran saat lingkungan terus membaik (detail dalam posting blog oleh Gilles Dubuc).
Jika Anda ingin menargetkan pasar yang sedang berkembang seperti Asia Tenggara, Afrika, atau India, Anda harus melihat serangkaian kendala yang sangat berbeda. Addy Osmani mencakup kendala ponsel berfitur utama, seperti sedikit biaya rendah, perangkat berkualitas tinggi, tidak tersedianya jaringan berkualitas tinggi dan data seluler yang mahal — bersama dengan anggaran PRPL-30 dan pedoman pengembangan untuk lingkungan ini.
Faktanya, Alex Russell dari Google merekomendasikan untuk membidik 130-170KB gzip sebagai batas atas yang masuk akal. Dalam skenario dunia nyata, sebagian besar produk bahkan tidak mendekati: ukuran bundel rata-rata saat ini adalah sekitar 452KB, yang naik 53,6% dibandingkan dengan awal 2015. Pada perangkat seluler kelas menengah, yang menyumbang 12-20 detik untuk Time -Untuk-Interaktif .
Kami juga bisa melampaui anggaran ukuran bundel. Misalnya, kita dapat menetapkan anggaran kinerja berdasarkan aktivitas thread utama browser, yaitu waktu melukis sebelum memulai render, atau melacak CPU hog front-end. Alat seperti Calibre, SpeedCurve, dan Bundlesize dapat membantu Anda mengendalikan anggaran, dan dapat diintegrasikan ke dalam proses pembuatan Anda.
Terakhir, anggaran kinerja mungkin tidak boleh berupa nilai tetap . Tergantung pada koneksi jaringan, anggaran kinerja harus beradaptasi, tetapi muatan pada koneksi yang lebih lambat jauh lebih "mahal", terlepas dari bagaimana mereka digunakan.
Catatan : Mungkin terdengar aneh untuk menetapkan anggaran yang begitu kaku pada saat HTTP/2 yang meluas, 5G dan HTTP/3 yang akan datang, ponsel yang berkembang pesat, dan SPA yang berkembang pesat. Namun, mereka terdengar masuk akal ketika kita berurusan dengan sifat jaringan dan perangkat keras yang tidak dapat diprediksi, termasuk segala sesuatu mulai dari jaringan yang padat hingga infrastruktur yang berkembang perlahan, hingga batas data, browser proxy, mode hemat data, dan biaya roaming yang licik.
Mendefinisikan Lingkungan
- Pilih dan siapkan alat build Anda.
Jangan terlalu memperhatikan apa yang dianggap keren akhir-akhir ini. Tetap berpegang pada lingkungan Anda untuk membangun, baik itu Grunt, Gulp, Webpack, Parcel, atau kombinasi alat. Selama Anda mendapatkan hasil yang Anda butuhkan dan Anda tidak memiliki masalah dalam mempertahankan proses pembangunan Anda, Anda baik-baik saja.Di antara alat build, Rollup terus mendapatkan daya tarik, begitu pula Snowpack, tetapi Webpack tampaknya menjadi yang paling mapan, dengan ratusan plugin tersedia untuk mengoptimalkan ukuran build Anda. Hati-hati dengan Peta Jalan Webpack 2021.
Salah satu strategi paling menonjol yang muncul baru-baru ini adalah Granular chunking dengan Webpack di Next.js dan Gatsby untuk meminimalkan kode duplikat. Secara default, modul yang tidak dibagikan di setiap titik masuk dapat diminta untuk rute yang tidak menggunakannya. Ini akhirnya menjadi overhead karena lebih banyak kode yang diunduh daripada yang diperlukan. Dengan chunking granular di Next.js, kita dapat menggunakan file manifes build sisi server untuk menentukan chunk keluaran mana yang digunakan oleh titik masuk yang berbeda.
Dengan SplitChunksPlugin, beberapa potongan terpisah dibuat tergantung pada sejumlah kondisi untuk mencegah pengambilan kode duplikat di beberapa rute. Ini meningkatkan waktu buka halaman dan caching selama navigasi. Dikirim di Next.js 9.2 dan di Gatsby v2.20.7.
Memulai dengan Webpack bisa jadi sulit. Jadi jika Anda ingin mendalami Webpack, ada beberapa sumber yang bagus di luar sana:
- Dokumentasi Webpack — tentu saja — adalah titik awal yang baik, dan begitu pula Webpack — The Confusing Bits oleh Raja Rao dan An Annotated Webpack Config oleh Andrew Welch.
- Sean Larkin memiliki kursus gratis di Webpack: The Core Concepts dan Jeffrey Way telah merilis kursus gratis yang fantastis di Webpack untuk semua orang. Keduanya adalah pengantar yang bagus untuk menyelam ke dalam Webpack.
- Webpack Fundamentals adalah kursus 4 jam yang sangat komprehensif dengan Sean Larkin, dirilis oleh FrontendMasters.
- Contoh Webpack memiliki ratusan konfigurasi Webpack siap pakai, dikategorikan berdasarkan topik dan tujuan. Bonus: ada juga konfigurator konfigurasi Webpack yang menghasilkan file konfigurasi dasar.
- awesome-webpack adalah daftar kurasi dari sumber daya Webpack, perpustakaan, dan alat yang berguna, termasuk artikel, video, kursus, buku, dan contoh untuk proyek Angular, React, dan framework-agnostic.
- Perjalanan menuju pembuatan aset produksi cepat dengan Webpack adalah studi kasus Etsy tentang bagaimana tim beralih dari menggunakan sistem pembangunan JavaScript berbasis RequireJS ke menggunakan Webpack dan bagaimana mereka mengoptimalkan pembangunan mereka, mengelola lebih dari 13.200 aset dalam rata-rata 4 menit .
- Kiat kinerja Webpack adalah utas tambang emas oleh Ivan Akulov, yang menampilkan banyak kiat yang berfokus pada kinerja, termasuk yang secara khusus berfokus pada Webpack.
- awesome-webpack-perf adalah repo GitHub tambang emas dengan alat dan plugin Webpack yang berguna untuk kinerja. Juga dikelola oleh Ivan Akulov.
- Gunakan peningkatan progresif sebagai default.
Namun, setelah bertahun-tahun, menjaga peningkatan progresif sebagai prinsip panduan arsitektur dan penerapan front-end Anda adalah taruhan yang aman. Rancang dan bangun pengalaman inti terlebih dahulu, lalu tingkatkan pengalaman dengan fitur-fitur canggih untuk browser yang mumpuni, menciptakan pengalaman yang tangguh. Jika situs web Anda berjalan cepat di mesin yang lambat dengan layar yang buruk di browser yang buruk di jaringan yang kurang optimal, maka itu hanya akan berjalan lebih cepat di mesin yang cepat dengan browser yang bagus di jaringan yang layak.Faktanya, dengan penyajian modul adaptif, kami tampaknya membawa peningkatan progresif ke tingkat lain, menyajikan pengalaman inti "ringan" ke perangkat kelas bawah, dan meningkatkan dengan fitur yang lebih canggih untuk perangkat kelas atas. Peningkatan progresif sepertinya tidak akan hilang dalam waktu dekat.
- Pilih dasar kinerja yang kuat.
Dengan begitu banyak hal yang tidak diketahui yang memengaruhi pemuatan — jaringan, pembatasan termal, pengusiran cache, skrip pihak ketiga, pola pemblokiran parser, I/O disk, latensi IPC, ekstensi yang diinstal, perangkat lunak antivirus dan firewall, tugas CPU latar belakang, kendala perangkat keras dan memori, perbedaan dalam L2/L3 caching, RTTS — JavaScript memiliki biaya pengalaman terberat, di samping font web memblokir rendering secara default dan gambar sering menghabiskan terlalu banyak memori. Dengan kemacetan kinerja yang berpindah dari server ke klien, sebagai pengembang, kami harus mempertimbangkan semua hal yang tidak diketahui ini dengan lebih detail.Dengan anggaran 170KB yang sudah berisi jalur kritis HTML/CSS/JavaScript, router, manajemen status, utilitas, kerangka kerja, dan logika aplikasi, kami harus memeriksa secara menyeluruh biaya transfer jaringan, waktu parse/kompilasi, dan biaya runtime. dari kerangka pilihan kita. Untungnya, kami telah melihat peningkatan besar selama beberapa tahun terakhir dalam seberapa cepat browser dapat mengurai dan mengkompilasi skrip. Namun eksekusi JavaScript masih menjadi hambatan utama, jadi memperhatikan waktu eksekusi skrip dan jaringan dapat berdampak.
Tim Kadlec telah melakukan penelitian fantastis tentang kinerja kerangka kerja modern, dan merangkumnya dalam artikel "Kerangka kerja JavaScript memiliki biaya". Kami sering berbicara tentang dampak kerangka kerja mandiri, tetapi seperti yang dicatat oleh Tim, dalam praktiknya, tidak jarang ada banyak kerangka kerja yang digunakan . Mungkin jQuery versi lama yang perlahan-lahan bermigrasi ke kerangka kerja modern, bersama dengan beberapa aplikasi lawas yang menggunakan versi Angular yang lebih lama. Jadi, lebih masuk akal untuk mengeksplorasi biaya kumulatif byte JavaScript dan waktu eksekusi CPU yang dapat dengan mudah membuat pengalaman pengguna hampir tidak dapat digunakan, bahkan pada perangkat kelas atas.
Secara umum, kerangka kerja modern tidak memprioritaskan perangkat yang kurang kuat , sehingga pengalaman di ponsel dan di desktop sering kali akan sangat berbeda dalam hal kinerja. Menurut penelitian, situs dengan React atau Angular menghabiskan lebih banyak waktu pada CPU daripada yang lain (yang tentu saja tidak berarti bahwa React lebih mahal pada CPU daripada Vue.js).
Menurut Tim, satu hal yang jelas: "jika Anda menggunakan kerangka kerja untuk membangun situs Anda, Anda membuat trade-off dalam hal kinerja awal — bahkan dalam skenario terbaik."
- Evaluasi kerangka kerja dan dependensi.
Sekarang, tidak setiap proyek membutuhkan kerangka kerja dan tidak setiap halaman aplikasi satu halaman perlu memuat kerangka kerja. Dalam kasus Netflix, "menghapus React, beberapa perpustakaan dan kode aplikasi yang sesuai dari sisi klien mengurangi jumlah total JavaScript lebih dari 200KB, menyebabkan pengurangan lebih dari 50% pada Time-to-Interaktivitas Netflix untuk beranda keluar ." Tim kemudian memanfaatkan waktu yang dihabiskan oleh pengguna di halaman arahan untuk mengambil terlebih dahulu React untuk halaman berikutnya yang kemungkinan akan dikunjungi pengguna (baca terus untuk detailnya).Jadi bagaimana jika Anda menghapus kerangka kerja yang ada pada halaman kritis sama sekali? Dengan Gatsby, Anda dapat memeriksa gatsby-plugin-no-javascript yang menghapus semua file JavaScript yang dibuat oleh Gatsby dari file HTML statis. Di Vercel, Anda juga dapat mengizinkan penonaktifan JavaScript runtime dalam produksi untuk halaman tertentu (eksperimental).
Setelah kerangka kerja dipilih, kami akan tetap menggunakannya selama setidaknya beberapa tahun, jadi jika kami perlu menggunakannya, kami perlu memastikan pilihan kami diinformasikan dan dipertimbangkan dengan baik — dan itu berlaku terutama untuk metrik kinerja utama yang kami peduli.
Data menunjukkan bahwa, secara default, kerangka kerja cukup mahal: 58,6% halaman React mengirimkan lebih dari 1 MB JavaScript, dan 36% pemuatan halaman Vue.js memiliki First Contentful Paint <1,5s. Menurut sebuah studi oleh Ankur Sethi, "aplikasi React Anda tidak akan pernah memuat lebih cepat dari sekitar 1,1 detik pada rata-rata ponsel di India, tidak peduli seberapa banyak Anda mengoptimalkannya. Aplikasi Angular Anda akan selalu membutuhkan setidaknya 2,7 detik untuk boot. pengguna aplikasi Vue Anda perlu menunggu setidaknya 1 detik sebelum mereka dapat mulai menggunakannya." Anda mungkin tidak menargetkan India sebagai pasar utama Anda, tetapi pengguna yang mengakses situs Anda dengan kondisi jaringan yang kurang optimal akan memiliki pengalaman yang sebanding.
Tentu saja dimungkinkan untuk membuat SPA dengan cepat, tetapi mereka tidak cepat keluar dari kotak, jadi kita perlu memperhitungkan waktu dan upaya yang diperlukan untuk membuat dan mempertahankannya dengan cepat. Mungkin akan lebih mudah dengan memilih biaya kinerja dasar yang ringan sejak awal.
Jadi bagaimana kita memilih kerangka kerja ? Sebaiknya pertimbangkan setidaknya total biaya berdasarkan ukuran + waktu eksekusi awal sebelum memilih opsi; opsi ringan seperti Preact, Inferno, Vue, Svelte, Alpine atau Polymer dapat menyelesaikan pekerjaan dengan baik. Ukuran baseline Anda akan menentukan batasan untuk kode aplikasi Anda.
Seperti yang dicatat oleh Seb Markbage, cara yang baik untuk mengukur biaya awal untuk kerangka kerja adalah dengan merender tampilan terlebih dahulu, lalu menghapusnya, lalu merendernya lagi karena ini dapat memberi tahu Anda bagaimana skala kerangka kerja. Render pertama cenderung menghangatkan sekelompok kode yang dikompilasi dengan malas, yang dapat dimanfaatkan oleh pohon yang lebih besar saat skala. Render kedua pada dasarnya adalah emulasi tentang bagaimana penggunaan kembali kode pada halaman memengaruhi karakteristik kinerja seiring dengan semakin kompleksnya halaman.
Anda dapat mengevaluasi kandidat Anda (atau pustaka JavaScript apa pun secara umum) pada sistem penilaian skala 12 poin Sacha Greif dengan menjelajahi fitur, aksesibilitas, stabilitas, kinerja, ekosistem paket , komunitas, kurva pembelajaran, dokumentasi, perkakas, rekam jejak , tim, kompatibilitas, keamanan misalnya.
Anda juga dapat mengandalkan data yang dikumpulkan di web dalam jangka waktu yang lebih lama. Misalnya, Perf Track melacak kinerja framework dalam skala besar, menampilkan skor Core Web Vitals teragregasi asal untuk situs web yang dibuat di Angular, React, Vue, Polymer, Preact, Ember, Svelte, dan AMP. Anda bahkan dapat menentukan dan membandingkan situs web yang dibuat dengan Gatsby, Next.js atau Create React App, serta situs web yang dibuat dengan Nuxt.js (Vue) atau Sapper (Svelte).
Titik awal yang baik adalah memilih tumpukan default yang baik untuk aplikasi Anda. Gatsby (React), Next.js (React), Vuepress (Vue), Preact CLI, dan PWA Starter Kit menyediakan default yang wajar untuk pemuatan cepat di luar kotak pada rata-rata perangkat keras seluler. Juga, lihat panduan kinerja khusus kerangka kerja web.dev untuk React dan Angular ( terima kasih, Phillip! ).
Dan mungkin Anda bisa mengambil pendekatan yang sedikit lebih menyegarkan untuk membangun aplikasi satu halaman sekaligus — Turbolinks, library JavaScript 15KB yang menggunakan HTML alih-alih JSON untuk merender tampilan. Jadi ketika Anda mengikuti tautan, Turbolinks secara otomatis mengambil halaman, menukar
<body>
nya, dan menggabungkan<head>
nya, semua tanpa menimbulkan biaya pemuatan halaman penuh. Anda dapat memeriksa detail cepat dan dokumentasi lengkap tentang tumpukan (Hotwire).
- Render sisi klien atau rendering sisi server? Keduanya!
Itu percakapan yang cukup panas untuk dilakukan. Pendekatan utama adalah menyiapkan semacam boot progresif: Gunakan rendering sisi server untuk mendapatkan First Contenful Paint yang cepat, tetapi juga sertakan beberapa JavaScript minimal yang diperlukan untuk menjaga waktu-untuk-interaktif tetap dekat dengan First Contentful Paint. Jika JavaScript datang terlambat setelah FCP, browser akan mengunci utas utama saat mem-parsing, mengkompilasi, dan mengeksekusi JavaScript yang ditemukan terlambat, sehingga membelenggu interaktivitas situs atau aplikasi.Untuk menghindarinya, selalu pisahkan eksekusi fungsi menjadi tugas-tugas asinkron yang terpisah, dan jika memungkinkan gunakan
requestIdleCallback
. Pertimbangkan pemuatan lambat bagian UI menggunakan dukunganimport()
dinamis WebPack, menghindari biaya pemuatan, penguraian, dan kompilasi hingga pengguna benar-benar membutuhkannya ( terima kasih Addy! ).Seperti disebutkan di atas, Time to Interactive (TTI) memberi tahu kita waktu antara navigasi dan interaktivitas. Secara rinci, metrik ditentukan dengan melihat jendela lima detik pertama setelah konten awal dirender, di mana tidak ada tugas JavaScript yang membutuhkan waktu lebih dari 50 md ( Tugas Panjang ). Jika tugas lebih dari 50 ms terjadi, pencarian untuk jendela lima detik akan dimulai kembali. Akibatnya, browser pertama-tama akan menganggap bahwa itu mencapai Interactive , hanya untuk beralih ke Frozen , hanya untuk akhirnya beralih kembali ke Interactive .
Setelah kami mencapai Interactive , kami kemudian dapat — baik sesuai permintaan atau jika waktu memungkinkan — mem-boot bagian aplikasi yang tidak penting. Sayangnya, seperti yang diperhatikan oleh Paul Lewis, kerangka kerja biasanya tidak memiliki konsep prioritas sederhana yang dapat ditampilkan ke pengembang, dan karenanya booting progresif tidak mudah diterapkan dengan sebagian besar pustaka dan kerangka kerja.
Tetap saja, kita sedang menuju ke sana. Saat ini ada beberapa pilihan yang dapat kita jelajahi, dan Houssein Djirdeh dan Jason Miller memberikan gambaran yang sangat baik tentang opsi ini dalam pembicaraan mereka tentang Rendering di Web dan tulisan Jason dan Addy tentang Arsitektur Front-End Modern. Ikhtisar di bawah ini didasarkan pada karya bintang mereka.
- Rendering Sisi Server (SSR) Penuh
Di SSR klasik, seperti WordPress, semua permintaan ditangani sepenuhnya di server. Konten yang diminta dikembalikan sebagai halaman HTML yang sudah jadi dan browser dapat langsung merendernya. Oleh karena itu, aplikasi SSR tidak dapat benar-benar menggunakan DOM API, misalnya. Kesenjangan antara First Contentful Paint dan Time to Interactive biasanya kecil, dan halaman dapat langsung dirender saat HTML dialirkan ke browser.Ini menghindari bolak-balik tambahan untuk pengambilan data dan pembuatan templat pada klien, karena ditangani sebelum browser mendapat respons. Namun, kami berakhir dengan waktu berpikir server yang lebih lama dan akibatnya Time To First Byte dan kami tidak menggunakan fitur aplikasi modern yang responsif dan kaya.
- Rendering Statis
Kami membangun produk sebagai aplikasi satu halaman, tetapi semua halaman dirender sebelumnya ke HTML statis dengan JavaScript minimal sebagai langkah pembuatan. Itu berarti bahwa dengan rendering statis, kami menghasilkan file HTML individual untuk setiap URL yang mungkin sebelumnya, yang merupakan sesuatu yang tidak dapat dilakukan oleh banyak aplikasi. Tetapi karena HTML untuk halaman tidak harus dibuat dengan cepat, kita dapat mencapai Time To First Byte yang cepat secara konsisten. Dengan demikian, kami dapat menampilkan halaman arahan dengan cepat dan kemudian mengambil kerangka SPA untuk halaman berikutnya. Netflix telah mengadopsi pendekatan ini untuk mengurangi pemuatan dan Time-to-Interactive sebesar 50%. - Rendering Sisi Server Dengan (Re)Hidrasi (Rendering Universal, SSR + CSR)
Kita dapat mencoba menggunakan yang terbaik dari kedua dunia — pendekatan SSR dan CSR. Dengan campuran hidrasi, halaman HTML yang dikembalikan dari server juga berisi skrip yang memuat aplikasi sisi klien yang lengkap. Idealnya, itu mencapai First Contentful Paint (seperti SSR) yang cepat dan kemudian melanjutkan rendering dengan (re)hydration. Sayangnya, itu jarang terjadi. Lebih sering, halaman memang terlihat siap tetapi tidak dapat menanggapi masukan pengguna, menghasilkan klik marah dan pengabaian.Dengan React, kita dapat menggunakan modul
ReactDOMServer
pada server Node seperti Express, dan kemudian memanggil metoderenderToString
untuk merender komponen tingkat atas sebagai string HTML statis.Dengan Vue.js, kita dapat menggunakan vue-server-renderer untuk merender instance Vue ke dalam HTML menggunakan
renderToString
. Di Angular, kita dapat menggunakan@nguniversal
untuk mengubah permintaan klien menjadi halaman HTML yang sepenuhnya dirender oleh server. Pengalaman yang sepenuhnya dirender server juga dapat dicapai dengan Next.js (React) atau Nuxt.js (Vue).Pendekatan ini memiliki kelemahan. Akibatnya, kami mendapatkan fleksibilitas penuh dari aplikasi sisi klien sambil memberikan rendering sisi server yang lebih cepat, tetapi kami juga berakhir dengan kesenjangan yang lebih panjang antara First Contentful Paint dan Time To Interactive dan peningkatan First Input Delay. Rehidrasi sangat mahal, dan biasanya strategi ini saja tidak akan cukup baik karena sangat menunda Time To Interactive.
- Streaming Rendering Sisi Server Dengan Hidrasi Progresif (SSR + CSR)
Untuk meminimalkan kesenjangan antara Time To Interactive dan First Contentful Paint, kami merender beberapa permintaan sekaligus dan mengirimkan konten dalam potongan saat dibuat. Jadi kita tidak perlu menunggu string penuh HTML sebelum mengirim konten ke browser, dan karenanya meningkatkan Time To First Byte.Di React, alih-alih
renderToString()
, kita bisa menggunakan renderToNodeStream() untuk menyalurkan respons dan mengirim HTML ke dalam potongan. Di Vue, kita bisa menggunakan renderToStream() yang bisa disalurkan dan dialirkan. Dengan React Suspense, kita mungkin menggunakan rendering asinkron untuk tujuan itu juga.Di sisi klien, daripada mem-boot seluruh aplikasi sekaligus, kami mem-boot komponen secara bertahap . Bagian dari aplikasi pertama-tama dipecah menjadi skrip mandiri dengan pemecahan kode, dan kemudian dihidrasi secara bertahap (sesuai urutan prioritas kami). Faktanya, kita bisa menghidrasi komponen penting terlebih dahulu, sedangkan sisanya bisa terhidrasi nanti. Peran rendering sisi klien dan sisi server kemudian dapat didefinisikan secara berbeda per komponen. Kami kemudian juga dapat menunda hidrasi beberapa komponen hingga terlihat, atau diperlukan untuk interaksi pengguna, atau saat browser tidak digunakan.
Untuk Vue, Markus Oberlehner telah menerbitkan panduan untuk mengurangi Time To Interactive dari aplikasi SSR menggunakan hidrasi pada interaksi pengguna serta vue-lazy-hydration, plugin tahap awal yang memungkinkan hidrasi komponen pada visibilitas atau interaksi pengguna tertentu. Tim Angular mengerjakan hidrasi progresif dengan Ivy Universal. Anda juga dapat menerapkan hidrasi parsial dengan Preact dan Next.js.
- Rendering Trisomorfik
Dengan pekerja layanan di tempat, kita dapat menggunakan rendering server streaming untuk navigasi awal/non-JS, dan kemudian pekerja layanan mengambil rendering HTML untuk navigasi setelah diinstal. Dalam hal ini, pekerja layanan melakukan pra-perenderan konten dan mengaktifkan navigasi gaya SPA untuk merender tampilan baru di sesi yang sama. Bekerja dengan baik ketika Anda dapat berbagi templating dan kode perutean yang sama antara server, halaman klien, dan pekerja layanan.
- CSR Dengan Prarendering
Praperenderan mirip dengan perenderan sisi server tetapi alih-alih merender halaman di server secara dinamis, kami merender aplikasi ke HTML statis pada waktu pembuatan. Meskipun laman statis sepenuhnya interaktif tanpa banyak JavaScript sisi klien, pra- perenderan bekerja secara berbeda . Pada dasarnya ini menangkap keadaan awal aplikasi sisi klien sebagai HTML statis pada waktu pembuatan, sementara dengan prarender aplikasi harus di-boot pada klien agar halaman menjadi interaktif.Dengan Next.js, kita dapat menggunakan ekspor HTML statis dengan melakukan pra-render aplikasi ke HTML statis. Di Gatsby, generator situs statis open source yang menggunakan React, menggunakan metode
renderToStaticMarkup
alih-alih metoderenderToString
selama build, dengan potongan JS utama yang dimuat sebelumnya dan rute masa depan diambil sebelumnya, tanpa atribut DOM yang tidak diperlukan untuk halaman statis sederhana.Untuk Vue, kita dapat menggunakan Vuepress untuk mencapai tujuan yang sama. Anda juga dapat menggunakan prerender-loader dengan Webpack. Navi juga menyediakan rendering statis.
Hasilnya adalah Time To First Byte dan First Contentful Paint yang lebih baik, dan kami mengurangi jarak antara Time To Interactive dan First Contentful Paint. Kami tidak dapat menggunakan pendekatan ini jika kontennya diperkirakan akan banyak berubah. Plus, semua URL harus diketahui sebelumnya untuk menghasilkan semua halaman. Jadi beberapa komponen mungkin dirender menggunakan prarendering, tetapi jika kita membutuhkan sesuatu yang dinamis, kita harus mengandalkan aplikasi untuk mengambil konten.
- Rendering Sisi Klien (CSR) Penuh
Semua logika, rendering, dan booting dilakukan pada klien. Hasilnya biasanya kesenjangan besar antara Time To Interactive dan First Contentful Paint. Akibatnya, aplikasi sering terasa lamban karena seluruh aplikasi harus di-boot pada klien untuk merender apa pun.Karena JavaScript memiliki biaya kinerja, seiring dengan bertambahnya jumlah JavaScript dengan suatu aplikasi, pemecahan kode yang agresif dan penundaan JavaScript akan mutlak diperlukan untuk menjinakkan dampak JavaScript. Untuk kasus seperti itu, rendering sisi server biasanya akan menjadi pendekatan yang lebih baik jika tidak banyak interaktivitas yang diperlukan. Jika ini bukan pilihan, pertimbangkan untuk menggunakan The App Shell Model.
Secara umum, RSK lebih cepat dari CSR. Namun tetap saja, ini merupakan implementasi yang cukup sering untuk banyak aplikasi di luar sana.
Jadi, sisi klien atau sisi server? Secara umum, sebaiknya batasi penggunaan kerangka kerja sisi klien sepenuhnya pada halaman yang benar-benar membutuhkannya. Untuk aplikasi tingkat lanjut, bukanlah ide yang baik untuk mengandalkan rendering sisi server saja. Rendering server dan rendering klien adalah bencana jika dilakukan dengan buruk.
Baik Anda condong ke CSR atau SSR, pastikan Anda merender piksel penting sesegera mungkin dan meminimalkan kesenjangan antara rendering itu dan Time To Interactive. Pertimbangkan untuk melakukan pra-perenderan jika halaman Anda tidak banyak berubah, dan tunda booting kerangka kerja jika Anda bisa. Streaming HTML dalam potongan dengan rendering sisi server, dan terapkan hidrasi progresif untuk rendering sisi klien — dan hidrasi pada visibilitas, interaksi, atau selama waktu idle untuk mendapatkan yang terbaik dari kedua dunia.
- Rendering Sisi Server (SSR) Penuh
- Berapa banyak yang bisa kita layani secara statis?
Baik Anda bekerja pada aplikasi besar atau situs kecil, ada baiknya mempertimbangkan konten apa yang dapat disajikan secara statis dari CDN (yaitu JAM Stack), daripada dihasilkan secara dinamis dengan cepat. Bahkan jika Anda memiliki ribuan produk dan ratusan filter dengan banyak pilihan personalisasi, Anda mungkin masih ingin menyajikan halaman arahan penting Anda secara statis, dan memisahkan halaman-halaman ini dari kerangka pilihan Anda.Ada banyak generator situs statis dan halaman yang mereka hasilkan seringkali sangat cepat. The more content we can pre-build ahead of time instead of generating page views on a server or client at request time, the better performance we will achieve.
In Building Partially Hydrated, Progressively Enhanced Static Websites, Markus Oberlehner shows how to build out websites with a static site generator and an SPA, while achieving progressive enhancement and a minimal JavaScript bundle size. Markus uses Eleventy and Preact as his tools, and shows how to set up the tools, add partial hydration, lazy hydration, client entry file, configure Babel for Preact and bundle Preact with Rollup — from start to finish.
With JAMStack used on large sites these days, a new performance consideration appeared: the build time . In fact, building out even thousands of pages with every new deploy can take minutes, so it's promising to see incremental builds in Gatsby which improve build times by 60 times , with an integration into popular CMS solutions like WordPress, Contentful, Drupal, Netlify CMS and others.
Also, Next.js announced ahead-of-time and incremental static generation, which allows us to add new static pages at runtime and update existing pages after they've been already built, by re-rendering them in the background as traffic comes in.
Need an even more lightweight approach? In his talk on Eleventy, Alpine and Tailwind: towards a lightweight Jamstack, Nicola Goutay explains the differences between CSR, SSR and everything-in-between, and shows how to use a more lightweight approach — along with a GitHub repo that shows the approach in practice.
- Consider using PRPL pattern and app shell architecture.
Different frameworks will have different effects on performance and will require different strategies of optimization, so you have to clearly understand all of the nuts and bolts of the framework you'll be relying on. When building a web app, look into the PRPL pattern and application shell architecture. The idea is quite straightforward: Push the minimal code needed to get interactive for the initial route to render quickly, then use service worker for caching and pre-caching resources and then lazy-load routes that you need, asynchronously.
- Have you optimized the performance of your APIs?
APIs are communication channels for an application to expose data to internal and third-party applications via endpoints . When designing and building an API, we need a reasonable protocol to enable the communication between the server and third-party requests. Representational State Transfer ( REST ) is a well-established, logical choice: it defines a set of constraints that developers follow to make content accessible in a performant, reliable and scalable fashion. Web services that conform to the REST constraints, are called RESTful web services .As with good ol' HTTP requests, when data is retrieved from an API, any delay in server response will propagate to the end user, hence delaying rendering . When a resource wants to retrieve some data from an API, it will need to request the data from the corresponding endpoint. A component that renders data from several resources, such as an article with comments and author photos in each comment, may need several roundtrips to the server to fetch all the data before it can be rendered. Furthermore, the amount of data returned through REST is often more than what is needed to render that component.
If many resources require data from an API, the API might become a performance bottleneck. GraphQL provides a performant solution to these issues. Per se, GraphQL is a query language for your API, and a server-side runtime for executing queries by using a type system you define for your data. Unlike REST, GraphQL can retrieve all data in a single request , and the response will be exactly what is required, without over or under -fetching data as it typically happens with REST.
In addition, because GraphQL is using schema (metadata that tells how the data is structured), it can already organize data into the preferred structure, so, for example, with GraphQL, we could remove JavaScript code used for dealing with state management, producing a cleaner application code that runs faster on the client.
If you want to get started with GraphQL or encounter performance issues, these articles might be quite helpful:
- A GraphQL Primer: Why We Need A New Kind Of API by Eric Baer,
- A GraphQL Primer: The Evolution Of API Design by Eric Baer,
- Designing a GraphQL server for optimal performance by Leonardo Losoviz,
- GraphQL performance explained by Wojciech Trocki.
- Will you be using AMP or Instant Articles?
Depending on the priorities and strategy of your organization, you might want to consider using Google's AMP or Facebook's Instant Articles or Apple's Apple News. You can achieve good performance without them, but AMP does provide a solid performance framework with a free content delivery network (CDN), while Instant Articles will boost your visibility and performance on Facebook.The seemingly obvious benefit of these technologies for users is guaranteed performance , so at times they might even prefer AMP-/Apple News/Instant Pages-links over "regular" and potentially bloated pages. For content-heavy websites that are dealing with a lot of third-party content, these options could potentially help speed up render times dramatically.
Unless they don't. According to Tim Kadlec, for example, "AMP documents tend to be faster than their counterparts, but they don't necessarily mean a page is performant. AMP is not what makes the biggest difference from a performance perspective."
A benefit for the website owner is obvious: discoverability of these formats on their respective platforms and increased visibility in search engines.
Well, at least that's how it used to be. As AMP is no longer a requirement for Top Stories , publishers might be moving away from AMP to a traditional stack instead ( thanks, Barry! ).
Still, you could build progressive web AMPs, too, by reusing AMPs as a data source for your PWA. Downside? Obviously, a presence in a walled garden places developers in a position to produce and maintain a separate version of their content, and in case of Instant Articles and Apple News without actual URLs (thanks Addy, Jeremy!) .
- Choose your CDN wisely.
As mentioned above, depending on how much dynamic data you have, you might be able to "outsource" some part of the content to a static site generator, pushing it to a CDN and serving a static version from it, thus avoiding requests to the server. In fact, some of those generators are actually website compilers with many automated optimizations provided out of the box. As compilers add optimizations over time, the compiled output gets smaller and faster over time.Notice that CDNs can serve (and offload) dynamic content as well. So, restricting your CDN to static assets is not necessary. Double-check whether your CDN performs compression and conversion (eg image optimization and resizing at the edge), whether they provide support for servers workers, A/B testing, as well as edge-side includes, which assemble static and dynamic parts of pages at the CDN's edge (ie the server closest to the user), and other tasks. Also, check if your CDN supports HTTP over QUIC (HTTP/3).
Katie Hempenius has written a fantastic guide to CDNs that provides insights on how to choose a good CDN , how to finetune it and all the little things to keep in mind when evaluating one. In general, it's a good idea to cache content as aggressively as possible and enable CDN performance features like Brotli, TLS 1.3, HTTP/2, and HTTP/3.
Note : based on research by Patrick Meenan and Andy Davies, HTTP/2 prioritization is effectively broken on many CDNs, so be careful when choosing a CDN. Patrick has more details in his talk on HTTP/2 Prioritization ( thanks, Barry! ).
When choosing a CDN, you can use these comparison sites with a detailed overview of their features:
- Perbandingan CDN, matriks perbandingan CDN untuk Cloudfront, Aazure, KeyCDN, Fastly, Verizon, Stackpach, Akamai, dan banyak lainnya.
- CDN Perf mengukur kecepatan kueri untuk CDN dengan mengumpulkan dan menganalisis 300 juta pengujian setiap hari, dengan semua hasil berdasarkan data RUM dari pengguna di seluruh dunia. Periksa juga perbandingan Kinerja DNS dan Perbandingan Kinerja Cloud.
- CDN Planet Guides memberikan ikhtisar CDN untuk topik tertentu, seperti Serve Stale, Purge, Origin Shield, Prefetch, dan Compression.
- Almanak Web: Adopsi dan Penggunaan CDN memberikan wawasan tentang penyedia CDN teratas, manajemen RTT dan TLS mereka, waktu negosiasi TLS, adopsi HTTP/2, dan lainnya. (Sayangnya, datanya hanya dari 2019).
Pengoptimalan Aset
- Gunakan Brotli untuk kompresi teks biasa.
Pada tahun 2015, Google memperkenalkan Brotli, format data lossless open-source baru, yang sekarang didukung di semua browser modern. Pustaka Brotli open source, yang mengimplementasikan encoder dan decoder untuk Brotli, memiliki 11 tingkat kualitas yang telah ditentukan untuk encoder, dengan tingkat kualitas yang lebih tinggi menuntut lebih banyak CPU sebagai ganti rasio kompresi yang lebih baik. Kompresi yang lebih lambat pada akhirnya akan menghasilkan tingkat kompresi yang lebih tinggi, namun tetap saja, Brotli melakukan dekompresi dengan cepat. Perlu dicatat bahwa Brotli dengan tingkat kompresi 4 lebih kecil dan lebih cepat dikompresi daripada Gzip.Dalam praktiknya, Brotli tampaknya jauh lebih efektif daripada Gzip. Pendapat dan pengalaman berbeda, tetapi jika situs Anda sudah dioptimalkan dengan Gzip, Anda mungkin mengharapkan setidaknya peningkatan satu digit dan paling baik peningkatan dua digit dalam pengurangan ukuran dan pengaturan waktu FCP. Anda juga dapat memperkirakan penghematan kompresi Brotli untuk situs Anda.
Browser akan menerima Brotli hanya jika pengguna mengunjungi situs web melalui HTTPS. Brotli didukung secara luas, dan banyak CDN mendukungnya (Akamai, Netlify Edge, AWS, KeyCDN, Fastly (saat ini hanya sebagai pass-through), Cloudflare, CDN77) dan Anda dapat mengaktifkan Brotli bahkan pada CDN yang belum mendukungnya (dengan pekerja layanan).
Tangkapannya adalah karena mengompresi semua aset dengan Brotli pada tingkat kompresi tinggi itu mahal, banyak penyedia hosting tidak dapat menggunakannya dalam skala penuh hanya karena biaya overhead yang besar yang dihasilkannya. Faktanya, pada tingkat kompresi tertinggi, Brotli sangat lambat sehingga setiap potensi keuntungan dalam ukuran file dapat dibatalkan dengan jumlah waktu yang diperlukan server untuk mulai mengirim respons saat menunggu untuk mengompresi aset secara dinamis. (Tetapi jika Anda memiliki waktu selama waktu pembuatan dengan kompresi statis, tentu saja, pengaturan kompresi yang lebih tinggi lebih disukai.)
Ini mungkin berubah. Format file Brotli menyertakan kamus statis bawaan , dan selain berisi berbagai string dalam berbagai bahasa, format ini juga mendukung opsi untuk menerapkan banyak transformasi pada kata-kata tersebut, meningkatkan keserbagunaannya. Dalam penelitiannya, Felix Hanau telah menemukan cara untuk meningkatkan kompresi pada level 5 hingga 9 dengan menggunakan "subset kamus yang lebih khusus daripada default" dan mengandalkan header
Content-Type
untuk memberi tahu kompresor jika harus menggunakan kamus untuk HTML, JavaScript atau CSS. Hasilnya adalah "dampak kinerja yang dapat diabaikan (1% hingga 3% lebih banyak CPU dibandingkan dengan 12% biasanya) saat mengompresi konten web pada tingkat kompresi tinggi, menggunakan pendekatan penggunaan kamus terbatas."Selain itu, dengan penelitian Elena Kirilenko, kami dapat mencapai rekompresi Brotli yang cepat dan efisien menggunakan artefak kompresi sebelumnya. Menurut Elena, "setelah kami memiliki aset yang dikompresi melalui Brotli, dan kami mencoba untuk mengompresi konten dinamis saat itu juga, di mana konten tersebut menyerupai konten yang tersedia untuk kami sebelumnya, kami dapat mencapai peningkatan yang signifikan dalam waktu kompresi. "
Seberapa sering kasusnya? Misalnya dengan pengiriman subset bundel JavaScript (misalnya ketika bagian dari kode sudah di-cache pada klien atau dengan penyajian bundel dinamis dengan WebBundles). Atau dengan HTML dinamis berdasarkan template yang dikenal sebelumnya, atau font WOFF2 yang diatur secara dinamis . Menurut Elena, kita bisa mendapatkan peningkatan 5,3% pada kompresi dan peningkatan 39% pada kecepatan kompresi saat menghapus 10% konten, dan tingkat kompresi 3,2% lebih baik dan kompresi 26% lebih cepat, saat menghapus 50% konten.
Kompresi Brotli semakin baik, jadi jika Anda dapat mengabaikan biaya mengompresi aset statis secara dinamis, itu pasti sepadan dengan usaha. Tak perlu dikatakan bahwa Brotli dapat digunakan untuk semua muatan teks biasa — HTML, CSS, SVG, JavaScript, JSON, dan sebagainya.
Catatan : mulai awal tahun 2021, sekitar 60% respons HTTP dikirimkan tanpa kompresi berbasis teks, dengan 30,82% mengompresi dengan Gzip, dan 9,1% mengompresi dengan Brotli (baik di seluler maupun di desktop). Misalnya, 23,4% halaman Angular tidak dikompresi (melalui gzip atau Brotli). Namun seringkali menyalakan kompresi adalah salah satu kemenangan termudah untuk meningkatkan kinerja dengan flip sederhana dari sebuah saklar.
Strateginya? Prakompresi aset statis dengan Brotli+Gzip di level tertinggi dan kompres (dinamis) HTML dengan cepat dengan Brotli di level 4–6. Pastikan server menangani negosiasi konten untuk Brotli atau Gzip dengan benar.
- Apakah kami menggunakan pemuatan media adaptif dan petunjuk klien?
Itu berasal dari negeri berita lama, tetapi selalu menjadi pengingat yang baik untuk menggunakan gambar responsif dengansrcset
,sizes
dan elemen<picture>
. Khusus untuk situs dengan jejak media yang berat, kami dapat mengambil langkah lebih jauh dengan pemuatan media adaptif (dalam contoh ini React + Next.js), menyajikan pengalaman ringan ke jaringan lambat dan perangkat dengan memori rendah dan pengalaman penuh ke jaringan cepat dan tinggi -Perangkat memori. Dalam konteks React, kita dapat mencapainya dengan petunjuk klien di server dan kait adaptif-reaksi di klien.Masa depan gambar responsif mungkin berubah secara dramatis dengan adopsi petunjuk klien yang lebih luas. Petunjuk klien adalah bidang header permintaan HTTP, misalnya
DPR
,Viewport-Width
,Width
,Save-Data
,Accept
(untuk menentukan preferensi format gambar) dan lainnya. Mereka seharusnya memberi tahu server tentang spesifikasi browser, layar, koneksi pengguna, dll.Akibatnya, server dapat memutuskan cara mengisi tata letak dengan gambar berukuran tepat , dan hanya menyajikan gambar ini dalam format yang diinginkan. Dengan petunjuk klien, kami memindahkan pemilihan sumber daya dari markup HTML dan ke dalam negosiasi permintaan-tanggapan antara klien dan server.
Seperti yang dicatat Ilya Grigorik beberapa waktu lalu, petunjuk klien melengkapi gambar — itu bukan alternatif untuk gambar responsif. "Elemen
<picture>
menyediakan kontrol art-direction yang diperlukan dalam markup HTML. Petunjuk klien memberikan anotasi pada permintaan gambar yang dihasilkan yang mengaktifkan otomatisasi pemilihan sumber daya. Service Worker menyediakan kemampuan manajemen permintaan dan respons penuh pada klien."Seorang pekerja layanan dapat, misalnya, menambahkan nilai header petunjuk klien baru ke permintaan, menulis ulang URL dan mengarahkan permintaan gambar ke CDN, menyesuaikan respons berdasarkan konektivitas dan preferensi pengguna, dll. Ini berlaku tidak hanya untuk aset gambar tetapi untuk hampir semua permintaan lainnya juga.
Untuk klien yang mendukung petunjuk klien, seseorang dapat mengukur penghematan 42% byte pada gambar dan 1MB+ byte lebih sedikit untuk persentil ke-70+. Di Smashing Magazine, kami juga dapat mengukur peningkatan 19-32%. Petunjuk klien didukung di browser berbasis Chromium, tetapi masih dalam pertimbangan di Firefox.
Namun, jika Anda menyediakan markup gambar responsif normal dan tag
<meta>
untuk Petunjuk Klien, maka browser pendukung akan mengevaluasi markup gambar responsif dan meminta sumber gambar yang sesuai menggunakan header HTTP Petunjuk Klien. - Apakah kita menggunakan gambar responsif untuk gambar latar belakang?
Kita pasti harus! Denganimage-set
, sekarang didukung di Safari 14 dan di sebagian besar browser modern kecuali Firefox, kami juga dapat menyajikan gambar latar belakang yang responsif:background-image: url("fallback.jpg"); background-image: image-set( "photo-small.jpg" 1x, "photo-large.jpg" 2x, "photo-print.jpg" 600dpi);
Pada dasarnya kami dapat menyajikan gambar latar belakang beresolusi rendah dengan deskriptor
1x
, dan gambar beresolusi lebih tinggi dengan deskriptor2x
, dan bahkan gambar berkualitas cetak dengan deskriptor600dpi
. Hati-hati meskipun: browser tidak memberikan informasi khusus tentang gambar latar belakang untuk membantu teknologi, jadi idealnya foto-foto ini hanya akan menjadi hiasan. - Apakah kita menggunakan WebP?
Kompresi gambar sering dianggap sebagai kemenangan cepat, namun dalam praktiknya masih sangat kurang dimanfaatkan. Tentu saja gambar tidak memblokir rendering, tetapi mereka sangat berkontribusi pada skor LCP yang buruk, dan sangat sering mereka terlalu berat dan terlalu besar untuk perangkat yang mereka gunakan.Jadi paling tidak, kita bisa menjelajah menggunakan format WebP untuk gambar kita. Faktanya, kisah WebP telah mendekati akhir tahun lalu dengan Apple menambahkan dukungan untuk WebP di Safari 14. Jadi setelah bertahun-tahun berdiskusi dan berdebat, hingga hari ini, WebP didukung di semua browser modern. Jadi kami dapat menyajikan gambar WebP dengan elemen
<picture>
dan mundur JPEG jika diperlukan (lihat cuplikan kode Andreas Bovens) atau dengan menggunakan negosiasi konten (menggunakan headerAccept
).WebP bukannya tanpa kerugian . Sementara ukuran file gambar WebP dibandingkan dengan Guetzli dan Zopfli yang setara, formatnya tidak mendukung rendering progresif seperti JPEG, itulah sebabnya pengguna mungkin melihat gambar jadi lebih cepat dengan JPEG lama meskipun gambar WebP mungkin semakin cepat melalui jaringan. Dengan JPEG, kami dapat menyajikan pengalaman pengguna yang "layak" dengan setengah atau bahkan seperempat data dan memuat sisanya nanti, daripada memiliki gambar setengah kosong seperti dalam kasus WebP.
Keputusan Anda akan tergantung pada apa yang Anda cari: dengan WebP, Anda akan mengurangi muatan, dan dengan JPEG Anda akan meningkatkan kinerja yang dirasakan. Anda dapat mempelajari lebih lanjut tentang WebP di WebP Rewind talk oleh Pascal Massimino dari Google.
Untuk konversi ke WebP, Anda dapat menggunakan Konverter WebP, cwebp atau libwebp. Ire Aderinokun juga memiliki tutorial yang sangat mendetail tentang mengonversi gambar ke WebP — dan begitu pula Josh Comeau dalam karyanya tentang merangkul format gambar modern.
Sketch secara native mendukung WebP, dan gambar WebP dapat diekspor dari Photoshop menggunakan plugin WebP untuk Photoshop. Tetapi opsi lain juga tersedia.
Jika Anda menggunakan WordPress atau Joomla, ada ekstensi untuk membantu Anda dengan mudah menerapkan dukungan untuk WebP, seperti Optimus dan Cache Enabler untuk WordPress dan ekstensi yang didukung Joomla sendiri (melalui Cody Arsenault). Anda juga dapat mengabstraksi elemen
<picture>
dengan React, komponen bergaya, atau gatsby-image.Ah — steker tak tahu malu! — Jeremy Wagner bahkan menerbitkan buku Smashing di WebP yang mungkin ingin Anda periksa apakah Anda tertarik dengan segala sesuatu di sekitar WebP.
- Apakah kita menggunakan AVIF?
Anda mungkin pernah mendengar berita besar: AVIF telah mendarat. Ini adalah format gambar baru yang berasal dari bingkai utama video AV1. Ini adalah format terbuka, bebas royalti yang mendukung kompresi lossy dan lossless, animasi, saluran alfa lossy dan dapat menangani garis tajam dan warna solid (yang merupakan masalah dengan JPEG), sambil memberikan hasil yang lebih baik di keduanya.Faktanya, dibandingkan dengan WebP dan JPEG, kinerja AVIF secara signifikan lebih baik , menghasilkan penghematan ukuran file median hingga 50% pada DSSIM ((dis)similarity yang sama antara dua atau lebih gambar menggunakan algoritme yang mendekati penglihatan manusia). Bahkan, dalam posting menyeluruhnya tentang mengoptimalkan pemuatan gambar, Malte Ubl mencatat bahwa AVIF "sangat konsisten mengungguli JPEG dalam cara yang sangat signifikan. Ini berbeda dari WebP yang tidak selalu menghasilkan gambar yang lebih kecil dari JPEG dan mungkin sebenarnya merupakan jaringan net- kerugian karena kurangnya dukungan untuk pemuatan progresif."
Ironisnya, AVIF dapat tampil lebih baik daripada SVG besar meskipun tentu saja tidak boleh dilihat sebagai pengganti SVG. Ini juga merupakan salah satu format gambar pertama yang mendukung dukungan warna HDR; menawarkan kecerahan yang lebih tinggi, kedalaman bit warna, dan gamut warna. Satu-satunya downside adalah bahwa saat ini AVIF tidak mendukung decoding gambar progresif (belum?) Dan, mirip dengan Brotli, pengkodean tingkat kompresi tinggi saat ini cukup lambat, meskipun decoding cepat.
AVIF saat ini didukung di Chrome, Firefox dan Opera, dan dukungan di Safari diharapkan akan segera hadir (karena Apple adalah anggota grup yang membuat AV1).
Apa cara terbaik untuk menyajikan gambar hari ini ? Untuk ilustrasi dan gambar vektor, SVG (terkompresi) tidak diragukan lagi merupakan pilihan terbaik. Untuk foto, kami menggunakan metode negosiasi konten dengan elemen
picture
. Jika AVIF didukung, kami mengirim gambar AVIF; jika tidak, kami kembali ke WebP terlebih dahulu, dan jika WebP juga tidak didukung, kami beralih ke JPEG atau PNG sebagai mundur (menerapkan kondisi@media
jika diperlukan):<picture> <source type="image/avif"> <source type="image/webp"> <img src="image.jpg" alt="Photo" width="450" height="350"> </picture>
Terus terang, kemungkinan besar kita akan menggunakan beberapa kondisi di dalam elemen
picture
:<picture> <source type="image/avif" /> <source type="image/webp" /> <source type="image/jpeg" /> <img src="fallback-image.jpg" alt="Photo" width="450" height="350"> </picture>
<picture> <source type="image/avif" /> <source type="image/webp" /> <source type="image/jpeg" /> <img src="fallback-image.jpg" alt="Photo" width="450" height="350"> </picture>
Anda dapat melangkah lebih jauh dengan menukar gambar animasi dengan gambar statis untuk pelanggan yang memilih lebih sedikit gerakan dengan gerakan
prefers-reduced-motion
pilihan :<picture> <source media="(prefers-reduced-motion: reduce)" type="image/avif"></source> <source media="(prefers-reduced-motion: reduce)" type="image/jpeg"></source> <source type="image/avif"></source> <img src="motion.jpg" alt="Animated AVIF"> </picture>
<picture> <source media="(prefers-reduced-motion: reduce)" type="image/avif"></source> <source media="(prefers-reduced-motion: reduce)" type="image/jpeg"></source> <source type="image/avif"></source> <img src="motion.jpg" alt="Animated AVIF"> </picture>
Selama beberapa bulan, AVIF telah mendapatkan beberapa daya tarik:
- Kita dapat menguji fallback WebP/AVIF di panel Rendering di DevTools.
- Kita dapat menggunakan Squoosh, AVIF.io dan libavif untuk menyandikan, mendekode, mengompres, dan mengonversi file AVIF.
- Kita dapat menggunakan komponen AVIF Preact Jake Archibald yang mendekode file AVIF di pekerja dan menampilkan hasilnya di kanvas,
- Untuk mengirimkan AVIF hanya ke browser pendukung, kita dapat menggunakan plugin PostCSS bersama dengan skrip 315B untuk menggunakan AVIF dalam deklarasi CSS Anda.
- Kami secara progresif dapat mengirimkan format gambar baru dengan CSS dan Cloudlare Worker untuk secara dinamis mengubah dokumen HTML yang dikembalikan, menyimpulkan informasi dari header
accept
, dan kemudian menambahkan kelaswebp/avif
dll. yang sesuai. - AVIF sudah tersedia di Cloudinary (dengan batas penggunaan), Cloudflare mendukung AVIF dalam Pengubahan Ukuran Gambar, dan Anda dapat mengaktifkan AVIF dengan Header AVIF Kustom di Netlify.
- Dalam hal animasi, AVIF berkinerja sebaik
<img src=mp4>
Safari, mengungguli GIF dan WebP pada umumnya, tetapi MP4 tetap berkinerja lebih baik. - Secara umum, untuk animasi, AVC1 (h264) > HVC1 > WebP > AVIF > GIF, dengan asumsi bahwa browser berbasis Chromium akan selalu mendukung
<img src=mp4>
. - Anda dapat menemukan detail lebih lanjut tentang AVIF di AVIF untuk Pembicaraan Pengodean Gambar Generasi Berikutnya oleh Aditya Mavlankar dari Netflix, dan Pembicaraan Format Gambar AVIF oleh Kornel Lesinski dari Cloudflare.
- Referensi bagus untuk semuanya AVIF: Pos komprehensif Jake Archibald tentang AVIF telah mendarat.
Jadi, apakah AVIF masa depan ? Jon Sneyers tidak setuju: AVIF berkinerja 60% lebih buruk daripada JPEG XL, format lain yang bebas dan terbuka yang dikembangkan oleh Google dan Cloudinary. Faktanya, JPEG XL tampaknya berkinerja jauh lebih baik secara keseluruhan. Namun, JPEG XL masih dalam tahap akhir standarisasi, dan belum berfungsi di browser apa pun. (Tidak bercampur dengan Microsoft JPEG-XR yang berasal dari Internet Explorer 9 kali).
- Apakah JPEG/PNG/SVG dioptimalkan dengan benar?
Saat Anda mengerjakan halaman arahan yang sangat penting agar gambar pahlawan dimuat dengan sangat cepat, pastikan JPEG progresif dan dikompresi dengan mozJPEG (yang meningkatkan waktu rendering awal dengan memanipulasi tingkat pemindaian) atau Guetzli, sumber terbuka Google encoder yang berfokus pada kinerja persepsi, dan memanfaatkan pembelajaran dari Zopfli dan WebP. Satu-satunya downside: waktu pemrosesan yang lambat (satu menit CPU per megapiksel).Untuk PNG, kita bisa menggunakan Pingo, dan untuk SVG, kita bisa menggunakan SVGO atau SVGOMG. Dan jika Anda perlu dengan cepat melihat pratinjau dan menyalin atau mengunduh semua aset SVG dari situs web, svg-grabber juga dapat melakukannya untuk Anda.
Setiap artikel pengoptimalan gambar akan menyatakannya, tetapi menjaga aset vektor tetap bersih dan rapat selalu layak untuk disebutkan. Pastikan untuk membersihkan aset yang tidak digunakan, menghapus metadata yang tidak perlu, dan mengurangi jumlah titik jalur dalam karya seni (dan dengan demikian kode SVG). ( Terima kasih, Jeremy! )
Ada juga alat online yang berguna yang tersedia:
- Gunakan Squoosh untuk mengompres, mengubah ukuran, dan memanipulasi gambar pada tingkat kompresi yang optimal (lossy atau lossless),
- Gunakan Guetzli.it untuk mengompresi dan mengoptimalkan gambar JPEG dengan Guetzli, yang bekerja dengan baik untuk gambar dengan tepi tajam dan warna solid (tetapi mungkin sedikit lebih lambat)).
- Gunakan Responsive Image Breakpoints Generator atau layanan seperti Cloudinary atau Imgix untuk mengotomatiskan pengoptimalan gambar. Juga, dalam banyak kasus, menggunakan
srcset
dansizes
saja akan menuai manfaat yang signifikan. - Untuk memeriksa efisiensi markup responsif, Anda dapat menggunakan imaging-heap, alat baris perintah yang mengukur efisiensi di seluruh ukuran viewport dan rasio piksel perangkat.
- Anda dapat menambahkan kompresi gambar otomatis ke alur kerja GitHub Anda, sehingga tidak ada gambar yang dapat mencapai produksi tanpa kompresi. Tindakan ini menggunakan mozjpeg dan libvips yang berfungsi dengan PNG dan JPG.
- Untuk mengoptimalkan penyimpanan secara internal, Anda dapat menggunakan format Lepton baru Dropbox untuk mengompresi JPEG tanpa kehilangan rata-rata 22%.
- Gunakan BlurHash jika Anda ingin menampilkan gambar placeholder lebih awal. BlurHash mengambil gambar, dan memberi Anda string pendek (hanya 20-30 karakter!) yang mewakili placeholder untuk gambar ini. String cukup pendek sehingga dapat dengan mudah ditambahkan sebagai bidang dalam objek JSON.
Terkadang mengoptimalkan gambar saja tidak akan berhasil. Untuk meningkatkan waktu yang diperlukan untuk memulai rendering gambar penting, muat lambat gambar yang kurang penting dan tunda skrip apa pun untuk dimuat setelah gambar penting selesai dirender. Cara yang paling antipeluru adalah hybrid lazy-loading, ketika kami menggunakan lazy-loading dan lazyload asli, sebuah library yang mendeteksi perubahan visibilitas yang dipicu melalui interaksi pengguna (dengan IntersectionObserver yang akan kita jelajahi nanti). Selain itu:
- Pertimbangkan untuk memuat gambar penting terlebih dahulu, sehingga browser tidak terlambat menemukannya. Untuk gambar latar belakang, jika Anda ingin lebih agresif dari itu, Anda dapat menambahkan gambar sebagai gambar biasa dengan
<img src>
, lalu menyembunyikannya dari layar. - Pertimbangkan Tukar Gambar dengan Atribut Ukuran dengan menentukan dimensi tampilan gambar yang berbeda tergantung pada kueri media, misalnya untuk memanipulasi
sizes
untuk menukar sumber dalam komponen kaca pembesar. - Tinjau inkonsistensi unduhan gambar untuk mencegah unduhan tak terduga untuk gambar latar depan dan latar belakang. Perhatikan gambar yang dimuat secara default, tetapi mungkin tidak pernah ditampilkan — misalnya di carousel, akordeon, dan galeri gambar.
- Pastikan untuk selalu mengatur
width
danheight
pada gambar. Perhatikan propertiaspect-ratio
dalam CSS dan atribut ukuranintrinsicsize
yang memungkinkan kita menyetel rasio aspek dan dimensi untuk gambar, sehingga browser dapat memesan slot tata letak yang telah ditentukan lebih awal untuk menghindari lompatan tata letak selama pemuatan halaman.
Jika Anda merasa ingin bertualang, Anda dapat memotong dan mengatur ulang aliran HTTP/2 menggunakan pekerja Edge, yang pada dasarnya adalah filter waktu nyata yang ada di CDN, untuk mengirim gambar lebih cepat melalui jaringan. Pekerja tepi menggunakan aliran JavaScript yang menggunakan potongan yang dapat Anda kontrol (pada dasarnya mereka adalah JavaScript yang berjalan di tepi CDN yang dapat memodifikasi respons streaming), sehingga Anda dapat mengontrol pengiriman gambar.
Dengan pekerja layanan, sudah terlambat karena Anda tidak dapat mengontrol apa yang ada di kabel, tetapi itu bekerja dengan pekerja Edge. Jadi Anda dapat menggunakannya di atas JPEG statis yang disimpan secara progresif untuk halaman arahan tertentu.
Tidak cukup baik? Nah, Anda juga dapat meningkatkan kinerja yang dirasakan untuk gambar dengan teknik beberapa gambar latar belakang. Ingatlah bahwa bermain dengan kontras dan mengaburkan detail yang tidak perlu (atau menghapus warna) juga dapat mengurangi ukuran file. Ah, Anda perlu memperbesar foto kecil tanpa kehilangan kualitas? Pertimbangkan untuk menggunakan Letsenhance.io.
Pengoptimalan ini sejauh ini hanya mencakup dasar-dasarnya. Addy Osmani telah menerbitkan panduan yang sangat rinci tentang Pengoptimalan Gambar Esensial yang membahas secara mendalam tentang kompresi gambar dan manajemen warna. Misalnya, Anda dapat mengaburkan bagian gambar yang tidak perlu (dengan menerapkan filter Gaussian blur pada bagian tersebut) untuk mengurangi ukuran file, dan pada akhirnya Anda bahkan mungkin mulai menghapus warna atau mengubah gambar menjadi hitam putih untuk mengurangi ukuran lebih jauh. . Untuk gambar latar belakang, mengekspor foto dari Photoshop dengan kualitas 0 hingga 10% juga dapat diterima.
Di Smashing Magazine, kami menggunakan postfix
-opt
untuk nama gambar — misalnya,brotli-compression-opt.png
; setiap kali sebuah gambar berisi postfix itu, semua orang di tim tahu bahwa gambar tersebut telah dioptimalkan.Ah, dan jangan gunakan JPEG-XR di web — "pemrosesan decoding sisi perangkat lunak JPEG-XR pada CPU membatalkan dan bahkan melebihi potensi dampak positif penghematan ukuran byte, terutama dalam konteks SPA" (tidak untuk mencampur dengan Cloudinary/Google's JPEG XL sekalipun).
- Apakah video dioptimalkan dengan benar?
Kami membahas gambar sejauh ini, tetapi kami menghindari percakapan tentang GIF yang bagus. Terlepas dari kecintaan kami pada GIF, inilah saatnya untuk meninggalkannya untuk selamanya (setidaknya di situs web dan aplikasi kami). Daripada memuat GIF animasi berat yang memengaruhi kinerja rendering dan bandwidth, sebaiknya beralih ke WebP animasi (dengan GIF sebagai fallback) atau menggantinya dengan video HTML5 perulangan sama sekali.Tidak seperti gambar, browser tidak memuat konten
<video>
sebelumnya, tetapi video HTML5 cenderung jauh lebih ringan dan lebih kecil daripada GIF. Bukan pilihan? Yah, setidaknya kita bisa menambahkan kompresi lossy ke GIF dengan Lossy GIF, gifsicle atau giflossy.Pengujian oleh Colin Bendell menunjukkan bahwa video sebaris dalam tag
img
di Pratinjau Teknologi Safari menampilkan setidaknya 20× lebih cepat dan memecahkan kode 7× lebih cepat daripada GIF yang setara, selain ukuran file yang lebih kecil. Namun, itu tidak didukung di browser lain.Di negeri berita baik, format video telah berkembang pesat selama bertahun-tahun. Untuk waktu yang lama, kami berharap bahwa WebM akan menjadi format untuk mengatur semuanya, dan WebP (yang pada dasarnya adalah satu gambar diam di dalam wadah video WebM) akan menjadi pengganti format gambar tanggal. Memang, Safari sekarang mendukung WebP, tetapi meskipun WebP dan WebM mendapatkan dukungan akhir-akhir ini, terobosan itu tidak benar-benar terjadi.
Namun, kami dapat menggunakan WebM untuk sebagian besar browser modern di luar sana:
<!-- By Houssein Djirdeh. https://web.dev/replace-gifs-with-videos/ --> <!-- A common scenartio: MP4 with a WEBM fallback. --> <video autoplay loop muted playsinline> <source src="my-animation.webm" type="video/webm"> <source src="my-animation.mp4" type="video/mp4"> </video>
Tapi mungkin kita bisa meninjaunya kembali sama sekali. Pada tahun 2018, Alliance of Open Media telah merilis format video baru yang menjanjikan yang disebut AV1 . AV1 memiliki kompresi yang mirip dengan codec H.265 (evolusi dari H.264) tetapi tidak seperti yang terakhir, AV1 gratis. Harga lisensi H.265 mendorong vendor browser untuk mengadopsi AV1 dengan performa yang sebanding: AV1 (seperti H.265) mengompres dua kali lebih baik dari WebM .
Faktanya, Apple saat ini menggunakan format HEIF dan HEVC (H.265), dan semua foto dan video di iOS terbaru disimpan dalam format ini, bukan JPEG. Meskipun HEIF dan HEVC (H.265) belum terekspos dengan benar ke web (belum?), AV1 sudah — dan mendapatkan dukungan browser. Jadi menambahkan sumber
AV1
di tag<video>
Anda adalah wajar, karena semua vendor browser tampaknya ikut serta.Untuk saat ini, encoding yang paling banyak digunakan dan didukung adalah H.264, dilayani oleh file MP4, jadi sebelum menyajikan file, pastikan MP4 Anda diproses dengan multipass-encoding, diburamkan dengan efek frei0r iirblur (jika ada) dan metadata atom moov dipindahkan ke kepala file, sementara server Anda menerima penyajian byte. Boris Schapira memberikan instruksi yang tepat untuk FFmpeg untuk mengoptimalkan video secara maksimal. Tentu saja, menyediakan format WebM sebagai alternatif juga akan membantu.
Perlu mulai merender video lebih cepat tetapi file video masih terlalu besar ? Misalnya, setiap kali Anda memiliki video latar belakang yang besar di halaman arahan? Teknik umum yang digunakan adalah menampilkan bingkai pertama sebagai gambar diam terlebih dahulu, atau menampilkan segmen pengulangan pendek yang dioptimalkan secara intensif yang dapat ditafsirkan sebagai bagian dari video, dan kemudian, kapan pun video cukup buffer, mulai putar video yang sebenarnya. Doug Sillars memiliki panduan terperinci tertulis untuk kinerja video latar belakang yang dapat membantu dalam kasus itu. ( Terima kasih, Guy Podjarny! ).
Untuk skenario di atas, Anda mungkin ingin memberikan gambar poster responsif . Secara default, elemen
video
hanya mengizinkan satu gambar sebagai poster, yang belum tentu optimal. Kami dapat menggunakan Poster Video Responsif, pustaka JavaScript yang memungkinkan Anda menggunakan gambar poster yang berbeda untuk layar yang berbeda, sambil menambahkan overlay transisi dan kontrol gaya penuh dari placeholder video.Penelitian menunjukkan bahwa kualitas streaming video memengaruhi perilaku pemirsa. Faktanya, penonton mulai mengabaikan video jika penundaan startup melebihi sekitar 2 detik. Di luar titik itu, peningkatan penundaan 1 detik menghasilkan peningkatan sekitar 5,8% dalam tingkat pengabaian. Jadi, tidak mengherankan jika median waktu mulai video adalah 12,8 detik, dengan 40% video memiliki setidaknya 1 jeda, dan 20% setidaknya 2 detik pemutaran video terhenti. Faktanya, video stall tidak dapat dihindari di 3G karena video diputar lebih cepat daripada yang dapat disediakan jaringan untuk konten.
Jadi, apa solusinya? Biasanya perangkat layar kecil tidak dapat menangani 720p dan 1080p yang kami layani desktop. Menurut Doug Sillars, kami dapat membuat versi yang lebih kecil dari video kami, dan menggunakan Javascript untuk mendeteksi sumber untuk layar yang lebih kecil guna memastikan pemutaran yang cepat dan lancar pada perangkat ini. Atau, kita dapat menggunakan video streaming. Aliran video HLS akan mengirimkan video berukuran tepat ke perangkat — mengabstraksi kebutuhan untuk membuat video yang berbeda untuk layar yang berbeda. Ini juga akan menegosiasikan kecepatan jaringan, dan menyesuaikan bitrate video dengan kecepatan jaringan yang Anda gunakan.
Untuk menghindari pemborosan bandwidth, kami hanya dapat menambahkan sumber video untuk perangkat yang benar-benar dapat memutar video dengan baik. Atau, kita dapat menghapus atribut
autoplay
dari tagvideo
sekaligus dan menggunakan JavaScript untuk menyisipkanautoplay
untuk layar yang lebih besar. Selain itu, kita perlu menambahkanpreload="none"
padavideo
untuk memberi tahu browser agar tidak mengunduh file video apa pun sampai benar-benar membutuhkan file:<!-- Based on Doug Sillars's post. https://dougsillars.com/2020/01/06/hiding-videos-on-the-mbile-web/ --> <video preload="none" playsinline muted loop width="1920" height="1080" poster="poster.jpg"> <source src="video.webm" type="video/webm"> <source src="video.mp4" type="video/mp4"> </video>
Kemudian kita dapat menargetkan secara khusus browser yang benar-benar mendukung AV1:
<!-- Based on Doug Sillars's post. https://dougsillars.com/2020/01/06/hiding-videos-on-the-mbile-web/ --> <video preload="none" playsinline muted loop width="1920" height="1080" poster="poster.jpg"> <source src="video.av1.mp4" type="video/mp4; codecs=av01.0.05M.08"> <source src="video.hevc.mp4" type="video/mp4; codecs=hevc"> <source src="video.webm" type="video/webm"> <source src="video.mp4" type="video/mp4"> </video>
Kami kemudian dapat menambahkan kembali
autoplay
di atas ambang tertentu (misalnya 1000px):/* By Doug Sillars. https://dougsillars.com/2020/01/06/hiding-videos-on-the-mbile-web/ */ <script> window.onload = addAutoplay(); var videoLocation = document.getElementById("hero-video"); function addAutoplay() { if(window.innerWidth > 1000){ videoLocation.setAttribute("autoplay",""); }; } </script>
Performa pemutaran video adalah cerita tersendiri, dan jika Anda ingin mempelajarinya secara mendetail, lihat seri Doug Sillars lainnya tentang Praktik Terbaik Pengiriman Video dan Video Keadaan Saat Ini yang menyertakan detail tentang metrik pengiriman video , pramuat video, kompresi, dan streaming. Terakhir, Anda dapat memeriksa seberapa lambat atau cepat streaming video Anda dengan Stream or Not.
- Apakah pengiriman font web dioptimalkan?
The first question that's worth asking is if we can get away with using UI system fonts in the first place — we just need to make sure to double check that they appear correctly on various platforms. If it's not the case, chances are high that the web fonts we are serving include glyphs and extra features and weights that aren't being used. We can ask our type foundry to subset web fonts or if we are using open-source fonts, subset them on our own with Glyphhanger or Fontsquirrel. We can even automate our entire workflow with Peter Muller's subfont, a command line tool that statically analyses your page in order to generate the most optimal web font subsets, and then inject them into our pages.WOFF2 support is great, and we can use WOFF as fallback for browsers that don't support it — or perhaps legacy browsers could be served system fonts. There are many, many, many options for web font loading, and we can choose one of the strategies from Zach Leatherman's "Comprehensive Guide to Font-Loading Strategies," (code snippets also available as Web font loading recipes).
Probably the better options to consider today are Critical FOFT with
preload
and "The Compromise" method. Both of them use a two-stage render for delivering web fonts in steps — first a small supersubset required to render the page fast and accurately with the web font, and then load the rest of the family async. The difference is that "The Compromise" technique loads polyfill asynchronously only if font load events are not supported, so you don't need to load the polyfill by default. Need a quick win? Zach Leatherman has a quick 23-min tutorial and case study to get your fonts in order.In general, it might be a good idea to use the
preload
resource hint to preload fonts, but in your markup include the hints after the link to critical CSS and JavaScript. Withpreload
, there is a puzzle of priorities, so consider injectingrel="preload"
elements into the DOM just before the external blocking scripts. According to Andy Davies, "resources injected using a script are hidden from the browser until the script executes, and we can use this behaviour to delay when the browser discovers thepreload
hint." Otherwise, font loading will cost you in the first render time.It's a good idea to be selective and choose files that matter most, eg the ones that are critical for rendering or that would help you avoiding visible and disruptive text reflows. In general, Zach advises to preload one or two fonts of each family — it also makes sense to delay some font loading if they are less critical.
It has become quite common to use
local()
value (which refers to a local font by name) when defining afont-family
in the@font-face
rule:/* Warning! Not a good idea! */ @font-face { font-family: Open Sans; src: local('Open Sans Regular'), local('OpenSans-Regular'), url('opensans.woff2') format ('woff2'), url('opensans.woff') format('woff'); }
The idea is reasonable: some popular open-source fonts such as Open Sans are coming pre-installed with some drivers or apps, so if the font is available locally, the browser doesn't need to download the web font and can display the local font immediately. As Bram Stein noted, "though a local font matches the name of a web font, it most likely isn't the same font . Many web fonts differ from their "desktop" version. The text might be rendered differently, some characters may fall back to other fonts, OpenType features can be missing entirely, or the line height may be different."
Also, as typefaces evolve over time, the locally installed version might be very different from the web font, with characters looking very different. So, according to Bram, it's better to never mix locally installed fonts and web fonts in
@font-face
rules. Google Fonts has followed suit by disablinglocal()
on the CSS results for all users, other than Android requests for Roboto.Nobody likes waiting for the content to be displayed. With the
font-display
CSS descriptor, we can control the font loading behavior and enable content to be readable immediately (withfont-display: optional
) or almost immediately (with a timeout of 3s, as long as the font gets successfully downloaded — withfont-display: swap
). (Well, it's a bit more complicated than that.)However, if you want to minimize the impact of text reflows, we could use the Font Loading API (supported in all modern browsers). Specifically that means for every font, we'd creata a
FontFace
object, then try to fetch them all, and only then apply them to the page. This way, we group all repaints by loading all fonts asynchronously, and then switch from fallback fonts to the web font exactly once. Take a look at Zach's explanation, starting at 32:15, and the code snippet):/* Load two web fonts using JavaScript */ /* Zach Leatherman: https://noti.st/zachleat/KNaZEg/the-five-whys-of-web-font-loading-performance#sWkN4u4 */ // Remove existing @font-face blocks // Create two let font = new FontFace("Noto Serif", /* ... */); let fontBold = new FontFace("Noto Serif, /* ... */); // Load two fonts let fonts = await Promise.all([ font.load(), fontBold.load() ]) // Group repaints and render both fonts at the same time! fonts.forEach(font => documents.fonts.add(font));
/* Load two web fonts using JavaScript */ /* Zach Leatherman: https://noti.st/zachleat/KNaZEg/the-five-whys-of-web-font-loading-performance#sWkN4u4 */ // Remove existing @font-face blocks // Create two let font = new FontFace("Noto Serif", /* ... */); let fontBold = new FontFace("Noto Serif, /* ... */); // Load two fonts let fonts = await Promise.all([ font.load(), fontBold.load() ]) // Group repaints and render both fonts at the same time! fonts.forEach(font => documents.fonts.add(font));
To initiate a very early fetch of the fonts with Font Loading API in use, Adrian Bece suggests to add a non-breaking space
nbsp;
at the top of thebody
, and hide it visually witharia-visibility: hidden
and a.hidden
class:<body class="no-js"> <!-- ... Website content ... --> <div aria-visibility="hidden" class="hidden"> <!-- There is a non-breaking space here --> </div> <script> document.getElementsByTagName("body")[0].classList.remove("no-js"); </script> </body>
<body class="no-js"> <!-- ... Website content ... --> <div aria-visibility="hidden" class="hidden"> <!-- There is a non-breaking space here --> </div> <script> document.getElementsByTagName("body")[0].classList.remove("no-js"); </script> </body>
This goes along with CSS that has different font families declared for different states of loading, with the change triggered by Font Loading API once the fonts have successfully loaded:
body:not(.wf-merriweather--loaded):not(.no-js) { font-family: [fallback-system-font]; /* Fallback font styles */ } .wf-merriweather--loaded, .no-js { font-family: "[web-font-name]"; /* Webfont styles */ } /* Accessible hiding */ .hidden { position: absolute; overflow: hidden; clip: rect(0 0 0 0); height: 1px; width: 1px; margin: -1px; padding: 0; border: 0; }
body:not(.wf-merriweather--loaded):not(.no-js) { font-family: [fallback-system-font]; /* Fallback font styles */ } .wf-merriweather--loaded, .no-js { font-family: "[web-font-name]"; /* Webfont styles */ } /* Accessible hiding */ .hidden { position: absolute; overflow: hidden; clip: rect(0 0 0 0); height: 1px; width: 1px; margin: -1px; padding: 0; border: 0; }
If you ever wondered why despite all your optimizations, Lighthouse still suggests to eliminate render-blocking resources (fonts), in the same article Adrian Bece provides a few techniques to make Lighthouse happy, along with a Gatsby Omni Font Loader, a performant asynchronous font loading and Flash Of Unstyled Text (FOUT) handling plugin for Gatsby.
Now, many of us might be using a CDN or a third-party host to load web fonts from. In general, it's always better to self-host all your static assets if you can, so consider using google-webfonts-helper, a hassle-free way to self-host Google Fonts. And if it's not possible, you can perhaps proxy the Google Font files through the page origin.
It's worth noting though that Google is doing quite a bit of work out of the box, so a server might need a bit of tweaking to avoid delays ( thanks, Barry! )
This is quite important especially as since Chrome v86 (released October 2020), cross-site resources like fonts can't be shared on the same CDN anymore — due to the partitioned browser cache. This behavior was a default in Safari for years.
But if it's not possible at all, there is a way to get to the fastest possible Google Fonts with Harry Roberts' snippet:
<!-- By Harry Roberts. https://csswizardry.com/2020/05/the-fastest-google-fonts/ - 1. Preemptively warm up the fonts' origin. - 2. Initiate a high-priority, asynchronous fetch for the CSS file. Works in - most modern browsers. - 3. Initiate a low-priority, asynchronous fetch that gets applied to the page - only after it's arrived. Works in all browsers with JavaScript enabled. - 4. In the unlikely event that a visitor has intentionally disabled - JavaScript, fall back to the original method. The good news is that, - although this is a render-blocking request, it can still make use of the - preconnect which makes it marginally faster than the default. --> <!-- [1] --> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> <!-- [2] --> <link rel="preload" as="style" href="$CSS&display=swap" /> <!-- [3] --> <link rel="stylesheet" href="$CSS&display=swap" media="print" onload="this.media='all'" /> <!-- [4] --> <noscript> <link rel="stylesheet" href="$CSS&display=swap" /> </noscript>
Harry's strategy is to pre-emptively warm up the fonts' origin first. Then we initiate a high-priority, asynchronous fetch for the CSS file. Afterwards, we initiate a low-priority, asynchronous fetch that gets applied to the page only after it's arrived (with a print stylesheet trick). Finally, if JavaScript isn't supported, we fall back to the original method.
Ah, talking about Google Fonts: you can shave up to 90% of the size of Google Fonts requests by declaring only characters you need with
&text
. Plus, the support for font-display was added recently to Google Fonts as well, so we can use it out of the box.Sebuah kata cepat dari hati-hati meskipun. Jika Anda menggunakan
font-display: optional
, mungkin tidak optimal juga menggunakanpreload
karena akan memicu permintaan font web lebih awal (menyebabkan kemacetan jaringan jika Anda memiliki sumber daya jalur penting lainnya yang perlu diambil). Gunakanpreconnect
untuk permintaan font lintas-asal yang lebih cepat, tetapi berhati-hatilah denganpreload
karena pramuat font dari asal yang berbeda akan menimbulkan pertentangan jaringan. Semua teknik ini tercakup dalam resep pemuatan font Web Zach.Di sisi lain, mungkin ide yang baik untuk menyisih dari font web (atau setidaknya render tahap kedua) jika pengguna telah mengaktifkan Kurangi Gerakan dalam preferensi aksesibilitas atau telah memilih untuk Mode Penghemat Data (lihat header
Save-Data
) , atau saat pengguna memiliki konektivitas yang lambat (melalui API Informasi Jaringan).Kami juga dapat menggunakan kueri media CSS
prefers-reduced-data
untuk tidak menentukan deklarasi font jika pengguna telah memilih mode hemat data (ada juga kasus penggunaan lainnya). Kueri media pada dasarnya akan terbuka jika header permintaanSave-Data
dari ekstensi HTTP Petunjuk Klien aktif/nonaktif untuk memungkinkan penggunaan dengan CSS. Saat ini hanya didukung di Chrome dan Edge di belakang bendera.Metrik? Untuk mengukur kinerja pemuatan font web, pertimbangkan metrik Semua Teks Terlihat (saat semua font telah dimuat dan semua konten ditampilkan dalam font web), Time to Real Italics, serta Web Font Reflow Count setelah render pertama. Jelas, semakin rendah kedua metrik, semakin baik kinerjanya.
Bagaimana dengan font variabel , Anda mungkin bertanya? Penting untuk diperhatikan bahwa font variabel mungkin memerlukan pertimbangan kinerja yang signifikan. Mereka memberi kami ruang desain yang jauh lebih luas untuk pilihan tipografi, tetapi itu harus dibayar dengan satu permintaan serial yang bertentangan dengan sejumlah permintaan file individual.
Sementara font variabel secara drastis mengurangi ukuran file gabungan keseluruhan file font, permintaan tunggal itu mungkin lambat, menghalangi rendering semua konten di halaman. Jadi subsetting dan pemisahan font menjadi set karakter masih penting. Sisi baiknya, dengan font variabel di tempat, kita akan mendapatkan tepat satu reflow secara default, jadi tidak ada JavaScript yang diperlukan untuk mengelompokkan pengecatan ulang.
Sekarang, apa yang akan membuat strategi pemuatan font web antipeluru ? Subset font dan siapkan untuk render 2 tahap, deklarasikan dengan deskriptor
font-display
, gunakan Font Loading API untuk mengelompokkan pengecatan ulang dan menyimpan font dalam cache pekerja layanan persisten. Pada kunjungan pertama, masukkan skrip preloading tepat sebelum skrip eksternal pemblokiran. Anda bisa kembali ke Pengamat Wajah Font Bram Stein jika perlu. Dan jika Anda tertarik untuk mengukur kinerja pemuatan font, Andreas Marschke mengeksplorasi pelacakan kinerja dengan Font API dan UserTiming API.Terakhir, jangan lupa untuk menyertakan
unicode-range
untuk memecah font besar menjadi font khusus bahasa yang lebih kecil, dan gunakan font-style-matcher Monica Dinculescu untuk meminimalkan pergeseran tata letak yang menggelegar, karena perbedaan ukuran antara fallback dan font web.Atau, untuk mengemulasi font web untuk font fallback, kita dapat menggunakan deskriptor @font-face untuk mengganti metrik font (demo, diaktifkan di Chrome 87). (Perhatikan bahwa penyesuaian rumit dengan tumpukan font yang rumit.)
Apakah masa depan terlihat cerah? Dengan pengayaan font progresif, pada akhirnya kami mungkin dapat "mengunduh hanya bagian font yang diperlukan pada halaman mana pun, dan untuk permintaan selanjutnya agar font tersebut secara dinamis 'menambal' unduhan asli dengan set mesin terbang tambahan seperti yang diperlukan pada halaman yang berurutan views", seperti yang dijelaskan Jason Pamental. Demo Transfer Inkremental sudah tersedia, dan sedang dalam proses.
Membangun Optimasi
- Sudahkah kita menentukan prioritas kita?
Ada baiknya untuk mengetahui apa yang Anda hadapi terlebih dahulu. Jalankan inventaris semua aset Anda (JavaScript, gambar, font, skrip pihak ketiga, dan modul "mahal" di halaman, seperti carousel, infografis kompleks, dan konten multimedia), dan pisahkan dalam grup.Siapkan spreadsheet . Tentukan pengalaman inti dasar untuk browser lawas (yaitu konten inti yang dapat diakses sepenuhnya), pengalaman yang disempurnakan untuk browser yang mumpuni (yaitu pengalaman penuh yang diperkaya) dan ekstra (aset yang tidak mutlak diperlukan dan dapat dimuat lambat, seperti font web, gaya yang tidak perlu, skrip carousel, pemutar video, widget media sosial, gambar besar). Bertahun-tahun yang lalu, kami menerbitkan sebuah artikel tentang "Meningkatkan Kinerja Majalah Smashing," yang menjelaskan pendekatan ini secara rinci.
Saat mengoptimalkan kinerja, kita perlu mencerminkan prioritas kita. Muat pengalaman inti segera, lalu peningkatan , dan kemudian ekstra .
- Apakah Anda menggunakan modul JavaScript asli dalam produksi?
Ingat teknik mutakhir yang bagus untuk mengirimkan pengalaman inti ke browser lawas dan pengalaman yang disempurnakan ke browser modern? Varian teknik yang diperbarui dapat menggunakan ES2017+<script type="module">
, juga dikenal sebagai module/nomodule pattern (juga diperkenalkan oleh Jeremy Wagner sebagai penyajian diferensial ).Idenya adalah untuk mengkompilasi dan menyajikan dua bundel JavaScript terpisah : build "reguler", yang dengan Babel-transforms dan polyfill dan menyajikannya hanya ke browser lawas yang benar-benar membutuhkannya, dan bundel lain (fungsi yang sama) yang tidak memiliki transformasi atau polifill.
Akibatnya, kami membantu mengurangi pemblokiran utas utama dengan mengurangi jumlah skrip yang perlu diproses browser. Jeremy Wagner telah memublikasikan artikel komprehensif tentang penyajian diferensial dan cara menyiapkannya di pipeline build Anda, mulai dari menyiapkan Babel, hingga tweak apa yang perlu Anda buat di Webpack, serta manfaat melakukan semua pekerjaan ini.
Skrip modul JavaScript asli ditangguhkan secara default, jadi saat penguraian HTML terjadi, browser akan mengunduh modul utama.
Satu catatan peringatan: pola module/nomodule dapat menjadi bumerang pada beberapa klien, jadi Anda mungkin ingin mempertimbangkan solusi: pola penyajian diferensial Jeremy yang kurang berisiko yang, bagaimanapun, menghindari pemindai pramuat, yang dapat memengaruhi kinerja dengan cara yang mungkin tidak mengantisipasi. ( terima kasih, jeremy! )
Faktanya, Rollup mendukung modul sebagai format output, sehingga kami dapat menggabungkan kode dan menerapkan modul dalam produksi. Parcel memiliki dukungan modul di Parcel 2. Untuk Webpack, module-nomodule-plugin mengotomatiskan pembuatan skrip modul/nomodule.
Catatan : Perlu dinyatakan bahwa deteksi fitur saja tidak cukup untuk membuat keputusan yang tepat tentang muatan yang akan dikirimkan ke browser tersebut. Dengan sendirinya, kami tidak dapat menyimpulkan kemampuan perangkat dari versi browser. Misalnya, ponsel Android murah di negara berkembang sebagian besar menjalankan Chrome dan akan memotong mustard meskipun memori dan kemampuan CPU mereka terbatas.
Akhirnya, dengan menggunakan Header Petunjuk Klien Memori Perangkat, kami akan dapat menargetkan perangkat kelas bawah dengan lebih andal. Pada saat penulisan, header hanya didukung di Blink (berlaku untuk petunjuk klien secara umum). Karena Memori Perangkat juga memiliki API JavaScript yang tersedia di Chrome, salah satu opsinya adalah dengan fitur deteksi berdasarkan API, dan kembali ke pola modul/nomodul jika tidak didukung ( terima kasih, Yoav! ).
- Apakah Anda menggunakan pengocokan pohon, pengangkatan ruang lingkup, dan pemecahan kode?
Pengocokan pohon adalah cara untuk membersihkan proses pembangunan Anda dengan hanya menyertakan kode yang benar-benar digunakan dalam produksi dan menghilangkan impor yang tidak digunakan di Webpack. Dengan Webpack dan Rollup, kami juga memiliki pengangkatan cakupan yang memungkinkan kedua alat mendeteksi di mana rantaiimport
dapat diratakan dan diubah menjadi satu fungsi sebaris tanpa mengorbankan kode. Dengan Webpack, kita juga bisa menggunakan JSON Tree Shaking.Pemisahan kode adalah fitur Webpack lain yang membagi basis kode Anda menjadi "potongan" yang dimuat sesuai permintaan. Tidak semua JavaScript harus diunduh, diurai, dan dikompilasi segera. Setelah Anda menentukan titik split dalam kode Anda, Webpack dapat menangani dependensi dan file yang dihasilkan. Ini memungkinkan Anda untuk menyimpan unduhan awal yang kecil dan untuk meminta kode sesuai permintaan saat diminta oleh aplikasi. Alexander Kondrov memiliki pengantar yang fantastis untuk pemecahan kode dengan Webpack dan React.
Pertimbangkan untuk menggunakan preload-webpack-plugin yang mengambil rute Anda dengan kode-split dan kemudian meminta browser untuk memuatnya terlebih dahulu menggunakan
<link rel="preload">
atau<link rel="prefetch">
. Arahan inline Webpack juga memberikan kontrol ataspreload
/prefetch
. (Hati-hati dengan masalah prioritas.)Di mana menentukan titik split? Dengan melacak potongan CSS/JavaScript mana yang digunakan, dan mana yang tidak digunakan. Umar Hansa menjelaskan bagaimana Anda dapat menggunakan Cakupan Kode dari Devtools untuk mencapainya.
Saat berurusan dengan aplikasi satu halaman, kita perlu waktu untuk menginisialisasi aplikasi sebelum kita bisa merender halaman. Pengaturan Anda akan memerlukan solusi khusus Anda, tetapi Anda dapat memperhatikan modul dan teknik untuk mempercepat waktu rendering awal. Misalnya, berikut ini cara men-debug kinerja React dan menghilangkan masalah kinerja React yang umum, dan inilah cara meningkatkan kinerja di Angular. Secara umum, sebagian besar masalah kinerja berasal dari waktu awal untuk mem-bootstrap aplikasi.
Jadi, apa cara terbaik untuk membagi kode secara agresif, tetapi tidak terlalu agresif? Menurut Phil Walton, "selain pemecahan kode melalui impor dinamis, [kita dapat] juga menggunakan pemecahan kode pada tingkat paket , di mana setiap modul simpul yang diimpor dimasukkan ke dalam potongan berdasarkan nama paketnya." Phil memberikan tutorial tentang cara membuatnya juga.
- Bisakah kita meningkatkan output Webpack?
Karena Webpack sering dianggap misterius, ada banyak plugin Webpack yang mungkin berguna untuk lebih mengurangi output Webpack. Di bawah ini adalah beberapa yang lebih tidak jelas yang mungkin memerlukan sedikit lebih banyak perhatian.Salah satu yang menarik datang dari utas Ivan Akulov. Bayangkan Anda memiliki fungsi yang Anda panggil sekali, simpan hasilnya dalam variabel, dan kemudian jangan gunakan variabel itu. Pengguncangan pohon akan menghapus variabel, tetapi bukan fungsinya, karena mungkin digunakan sebaliknya. Namun, jika fungsi tersebut tidak digunakan di mana pun, Anda mungkin ingin menghapusnya. Untuk melakukannya, tambahkan panggilan fungsi dengan
/*#__PURE__*/
yang didukung oleh Uglify dan Terser — selesai!Berikut adalah beberapa alat lain yang direkomendasikan Ivan:
- purgecss-webpack-plugin menghapus kelas yang tidak digunakan, terutama saat Anda menggunakan Bootstrap atau Tailwind.
- Aktifkan
optimization.splitChunks: 'all'
dengan plugin split-chunks. Ini akan membuat webpack secara otomatis memecah kode bundel entri Anda untuk caching yang lebih baik. - Setel
optimization.runtimeChunk: true
. Ini akan memindahkan runtime webpack ke bagian yang terpisah — dan juga akan meningkatkan caching. - google-fonts-webpack-plugin mengunduh file font, sehingga Anda dapat menyajikannya dari server Anda.
- workbox-webpack-plugin memungkinkan Anda membuat service worker dengan penyiapan pra-cache untuk semua aset webpack Anda. Juga, periksa Paket Service Worker, panduan modul komprehensif yang dapat langsung diterapkan. Atau gunakan preload-webpack-plugin untuk menghasilkan
preload
/prefetch
untuk semua potongan JavaScript. - speed-measure-webpack-plugin mengukur kecepatan build webpack Anda, memberikan wawasan tentang langkah-langkah proses build mana yang paling memakan waktu.
- duplikat-paket-pemeriksa-webpack-plugin memperingatkan ketika bundel Anda berisi beberapa versi dari paket yang sama.
- Gunakan isolasi ruang lingkup dan persingkat nama kelas CSS secara dinamis pada waktu kompilasi.
- Bisakah Anda membongkar JavaScript ke Web Worker?
Untuk mengurangi dampak negatif terhadap Time-to-Interactive, mungkin ide yang baik untuk mempertimbangkan pembongkaran JavaScript yang berat ke Web Worker.Saat basis kode terus berkembang, kemacetan kinerja UI akan muncul, memperlambat pengalaman pengguna. Itu karena operasi DOM berjalan bersama JavaScript Anda di utas utama. Dengan pekerja web, kami dapat memindahkan operasi mahal ini ke proses latar belakang yang berjalan di utas berbeda. Kasus penggunaan umum untuk pekerja web adalah mengambil data sebelumnya dan Aplikasi Web Progresif untuk memuat dan menyimpan beberapa data terlebih dahulu sehingga Anda dapat menggunakannya nanti saat dibutuhkan. Dan Anda dapat menggunakan Comlink untuk merampingkan komunikasi antara halaman utama dan pekerja. Masih ada beberapa pekerjaan yang harus dilakukan, tetapi kami sedang menuju ke sana.
Ada beberapa studi kasus menarik seputar pekerja web yang menunjukkan pendekatan berbeda untuk memindahkan kerangka kerja dan logika aplikasi ke pekerja web. Kesimpulannya: secara umum, masih ada beberapa tantangan, tetapi sudah ada beberapa kasus penggunaan yang baik ( terima kasih, Ivan Akulov! ).
Mulai dari Chrome 80, mode baru untuk pekerja web dengan manfaat kinerja modul JavaScript telah dikirimkan, yang disebut pekerja modul. Kita dapat mengubah pemuatan dan eksekusi skrip agar sesuai dengan
script type="module"
, ditambah lagi kita juga dapat menggunakan impor dinamis untuk kode pemuatan lambat tanpa memblokir eksekusi pekerja.Bagaimana cara memulai? Berikut adalah beberapa sumber daya yang layak untuk dilihat:
- Surma telah menerbitkan panduan yang sangat baik tentang cara menjalankan JavaScript dari utas utama browser dan juga Kapan Anda harus menggunakan Pekerja Web?
- Juga, periksa pembicaraan Surma tentang arsitektur utas utama.
- A Quest to Guarantee Responsiveness oleh Shubhie Panicker dan Jason Miller memberikan wawasan mendetail tentang cara menggunakan pekerja web, dan kapan harus menghindarinya.
- Keluar dari Cara Pengguna: Kurang Jank Dengan Pekerja Web menyoroti pola yang berguna untuk bekerja dengan Pekerja Web, cara efektif untuk berkomunikasi antar pekerja, menangani pemrosesan data yang kompleks dari utas utama, dan menguji serta men-debug mereka.
- Workerize memungkinkan Anda untuk memindahkan modul ke Web Worker, yang secara otomatis mencerminkan fungsi yang diekspor sebagai proxy asinkron.
- Jika Anda menggunakan Webpack, Anda bisa menggunakan workerize-loader. Atau, Anda juga bisa menggunakan plugin pekerja.
Perhatikan bahwa Pekerja Web tidak memiliki akses ke DOM karena DOM bukan "thread-safe", dan kode yang mereka jalankan harus dimuat dalam file terpisah.
- Bisakah Anda membongkar "jalur panas" ke WebAssembly?
Kami dapat memindahkan tugas komputasi berat ke WebAssembly ( WASM ), format instruksi biner, yang dirancang sebagai target portabel untuk kompilasi bahasa tingkat tinggi seperti C/C++/Rust. Dukungan browsernya luar biasa, dan baru-baru ini menjadi layak karena panggilan fungsi antara JavaScript dan WASM semakin cepat. Plus, itu bahkan didukung di cloud edge Fastly.Tentu saja, WebAssembly tidak seharusnya menggantikan JavaScript, tetapi dapat melengkapinya jika Anda melihat CPU hog. Untuk sebagian besar aplikasi web, JavaScript lebih cocok, dan WebAssembly paling baik digunakan untuk aplikasi web intensif komputasi , seperti game.
Jika Anda ingin mempelajari lebih lanjut tentang WebAssembly:
- Lin Clark telah menulis seri menyeluruh untuk WebAssembly dan Milica Mihajlija memberikan gambaran umum tentang cara menjalankan kode asli di browser, mengapa Anda mungkin ingin melakukan itu, dan apa artinya semua itu untuk JavaScript dan masa depan pengembangan web.
- Bagaimana Kami Menggunakan WebAssembly Untuk Mempercepat Aplikasi Web Kami Hingga 20X (Studi Kasus) menyoroti studi kasus tentang bagaimana perhitungan JavaScript yang lambat diganti dengan WebAssembly yang dikompilasi dan membawa peningkatan kinerja yang signifikan.
- Patrick Hamann telah berbicara tentang pertumbuhan peran WebAssembly, dan dia menyanggah beberapa mitos tentang WebAssembly, mengeksplorasi tantangannya dan kita dapat menggunakannya secara praktis dalam aplikasi saat ini.
- Google Codelabs menyediakan Pengantar WebAssembly, kursus 60 menit di mana Anda akan mempelajari cara mengambil kode asli—dalam C dan mengompilasinya ke WebAssembly, lalu memanggilnya langsung dari JavaScript.
- Alex Danilo telah menjelaskan WebAssembly dan cara kerjanya di pembicaraan Google I/O-nya. Selain itu, Benedek Gagyi membagikan studi kasus praktis di WebAssembly, khususnya bagaimana tim menggunakannya sebagai format keluaran untuk basis kode C++ mereka ke iOS, Android, dan situs web.
Masih tidak yakin kapan harus menggunakan Web Workers, Web Assembly, stream, atau mungkin WebGL JavaScript API untuk mengakses GPU? Akselerasi JavaScript adalah panduan singkat namun bermanfaat yang menjelaskan kapan harus menggunakan apa, dan mengapa — juga dengan diagram alur yang praktis dan banyak sumber daya yang berguna.
- Apakah kami hanya menyajikan kode lawas ke browser lawas?
Dengan ES2017 yang didukung dengan sangat baik di browser modern, kami dapat menggunakanbabelEsmPlugin
untuk hanya mentranspile fitur ES2017+ yang tidak didukung oleh browser modern yang Anda targetkan.Houssein Djirdeh dan Jason Miller baru-baru ini menerbitkan panduan komprehensif tentang cara mengubah dan menyajikan JavaScript modern dan lama, membahas detail membuatnya bekerja dengan Webpack dan Rollup, dan perkakas yang dibutuhkan. Anda juga dapat memperkirakan berapa banyak JavaScript yang dapat Anda kurangi di situs atau bundel aplikasi Anda.
Modul JavaScript didukung di semua browser utama, jadi gunakan gunakan
script type="module"
agar browser dengan dukungan modul ES memuat file, sementara browser lama dapat memuat build lawas denganscript nomodule
.Saat ini kita dapat menulis JavaScript berbasis modul yang berjalan secara native di browser, tanpa transpiler atau bundler.
<link rel="modulepreload">
header menyediakan cara untuk memulai pemuatan awal (dan prioritas tinggi) skrip modul. Pada dasarnya, ini adalah cara yang bagus untuk membantu memaksimalkan penggunaan bandwidth, dengan memberi tahu browser tentang apa yang perlu diambil sehingga tidak terjebak dengan apa pun yang harus dilakukan selama perjalanan pulang pergi yang panjang itu. Juga, Jake Archibald telah menerbitkan artikel terperinci dengan gotcha dan hal-hal yang perlu diingat dengan Modul ES yang layak dibaca.
- Identifikasi dan tulis ulang kode lama dengan decoupling tambahan .
Proyek berumur panjang memiliki kecenderungan untuk mengumpulkan debu dan kode tanggal. Kunjungi kembali dependensi Anda dan nilai berapa banyak waktu yang diperlukan untuk memfaktorkan ulang atau menulis ulang kode lama yang telah menyebabkan masalah akhir-akhir ini. Tentu saja, ini selalu merupakan tugas besar, tetapi begitu Anda mengetahui dampak dari kode lama, Anda bisa mulai dengan pemisahan tambahan.Pertama, siapkan metrik yang melacak jika rasio panggilan kode lama tetap konstan atau turun, bukan naik. Anjurkan tim untuk tidak menggunakan perpustakaan secara publik dan pastikan CI Anda memberi tahu pengembang jika digunakan dalam permintaan tarik. polyfills dapat membantu transisi dari kode lama ke basis kode yang ditulis ulang yang menggunakan fitur browser standar.
- Identifikasi dan hapus CSS/JS yang tidak digunakan .
Cakupan kode CSS dan JavaScript di Chrome memungkinkan Anda mempelajari kode mana yang telah dieksekusi/diterapkan dan mana yang belum. Anda dapat mulai merekam liputan, melakukan tindakan pada halaman, lalu menjelajahi hasil liputan kode. Setelah Anda mendeteksi kode yang tidak digunakan, temukan modul tersebut dan muat lambat denganimport()
(lihat seluruh utas). Kemudian ulangi profil cakupan dan validasi bahwa sekarang pengiriman kode lebih sedikit pada pemuatan awal.Anda dapat menggunakan Dalang untuk mengumpulkan cakupan kode secara terprogram. Chrome juga memungkinkan Anda mengekspor hasil cakupan kode. Seperti yang dicatat Andy Davies, Anda mungkin ingin mengumpulkan cakupan kode untuk browser modern dan lama.
Ada banyak kasus penggunaan dan alat lain untuk Wayang yang mungkin memerlukan sedikit lebih banyak pemaparan:
- Kasus penggunaan untuk Dalang, seperti, misalnya, visual diffing otomatis atau memantau CSS yang tidak digunakan dengan setiap build,
- resep kinerja web dengan Dalang,
- Alat yang berguna untuk merekam dan membuat skrip Pupeeteer dan Penulis Drama,
- Plus, Anda bahkan dapat merekam tes langsung di DevTools,
- Ikhtisar komprehensif Dalang oleh Nitay Neeman, dengan contoh dan kasus penggunaan.
Selanjutnya, purgecss, UnCSS dan Helium dapat membantu Anda menghapus gaya yang tidak digunakan dari CSS. Dan jika Anda tidak yakin apakah bagian kode yang mencurigakan digunakan di suatu tempat, Anda dapat mengikuti saran Harry Roberts: buat GIF transparan 1x1px untuk kelas tertentu dan letakkan di direktori
dead/
, misalnya/assets/img/dead/comments.gif
.Setelah itu, Anda menetapkan gambar tertentu sebagai latar belakang pada pemilih yang sesuai di CSS Anda, duduk dan tunggu beberapa bulan jika file tersebut akan muncul di log Anda. Jika tidak ada entri, tidak ada yang memiliki komponen lama yang dirender di layar mereka: Anda mungkin dapat melanjutkan dan menghapus semuanya.
Untuk departemen I-feel-adventurous , Anda bahkan dapat mengotomatiskan pengumpulan CSS yang tidak digunakan melalui serangkaian halaman dengan memantau DevTools menggunakan DevTools.
- Pangkas ukuran bundel JavaScript Anda.
Seperti yang dicatat Addy Osmani, ada kemungkinan besar Anda mengirimkan pustaka JavaScript lengkap saat Anda hanya membutuhkan sebagian kecil, bersama dengan polyfill bertanggal untuk browser yang tidak membutuhkannya, atau hanya kode duplikat. Untuk menghindari overhead, pertimbangkan untuk menggunakan webpack-libs-optimizations yang menghapus metode dan polyfill yang tidak digunakan selama proses build.Periksa dan tinjau polyfill yang Anda kirim ke browser lawas dan browser modern, dan jadilah lebih strategis tentangnya. Lihatlah polyfill.io yang merupakan layanan yang menerima permintaan untuk serangkaian fitur browser dan hanya mengembalikan polyfill yang dibutuhkan oleh browser yang meminta.
Tambahkan audit bundel ke dalam alur kerja reguler Anda juga. Mungkin ada beberapa alternatif ringan untuk perpustakaan berat yang telah Anda tambahkan bertahun-tahun yang lalu, misalnya Moment.js (sekarang dihentikan) dapat diganti dengan:
- API Internasionalisasi asli,
- Day.js dengan API dan pola Moment.js yang familier,
- tanggal-fns atau
- lukson.
- Anda juga dapat menggunakan Skypack Discover yang menggabungkan rekomendasi paket yang ditinjau oleh manusia dengan pencarian yang berfokus pada kualitas.
Penelitian Benedikt Rotsch menunjukkan bahwa peralihan dari Moment.js ke date-fns dapat mengurangi sekitar 300 ms untuk First paint di 3G dan ponsel kelas bawah.
Untuk audit bundel, Bundlephobia dapat membantu menemukan biaya penambahan paket npm ke bundel Anda. size-limit memperluas pemeriksaan ukuran bundel dasar dengan detail tentang waktu eksekusi JavaScript. Anda bahkan dapat mengintegrasikan biaya ini dengan Lighthouse Custom Audit. Ini juga berlaku untuk kerangka kerja. Dengan menghapus atau memangkas Adaptor MDC Vue (Komponen Material untuk Vue), gaya turun dari 194KB menjadi 10KB.
Ada banyak alat lebih lanjut untuk membantu Anda membuat keputusan yang tepat tentang dampak ketergantungan Anda dan alternatif yang layak:
- webpack-bundle-analyzer
- Penjelajah Peta Sumber
- Bundel Sobat
- Bundelfobia
- Analisis Webpack menunjukkan mengapa modul tertentu disertakan ke dalam bundel.
- bundle-wizard juga membuat peta dependensi untuk seluruh halaman.
- Plugin ukuran paket web
- Biaya Impor untuk Kode Visual
Atau untuk mengirimkan seluruh kerangka kerja, Anda dapat memangkas kerangka kerja Anda dan mengompilasinya menjadi bundel JavaScript mentah yang tidak memerlukan kode tambahan. Svelte melakukannya, dan begitu juga plugin Rawact Babel yang mentranspilasikan komponen React.js ke operasi DOM asli pada waktu pembuatan. Mengapa? Seperti yang dijelaskan oleh pengelola, "react-dom menyertakan kode untuk setiap komponen/HTMLElement yang mungkin dapat dirender, termasuk kode untuk rendering inkremental, penjadwalan, penanganan acara, dll. Tetapi ada aplikasi yang tidak memerlukan semua fitur ini (pada awalnya pemuatan halaman). Untuk aplikasi semacam itu, mungkin masuk akal untuk menggunakan operasi DOM asli untuk membangun antarmuka pengguna interaktif."
- Apakah kita menggunakan hidrasi parsial?
Dengan jumlah JavaScript yang digunakan dalam aplikasi, kita perlu mencari cara untuk mengirim sesedikit mungkin ke klien. Salah satu cara untuk melakukannya — dan kami sudah membahasnya secara singkat — adalah dengan hidrasi parsial. Idenya cukup sederhana: alih-alih melakukan SSR dan kemudian mengirim seluruh aplikasi ke klien, hanya sebagian kecil dari JavaScript aplikasi yang akan dikirim ke klien dan kemudian dihidrasi. Kita dapat menganggapnya sebagai beberapa aplikasi React kecil dengan beberapa root render di situs web yang statis.Dalam artikel "Kasus hidrasi parsial (dengan Berikutnya dan Preact)", Lukas Bombach menjelaskan bagaimana tim di belakang Welt.de, salah satu outlet berita di Jerman, telah mencapai kinerja yang lebih baik dengan hidrasi parsial. Anda juga dapat memeriksa repo GitHub berkinerja super berikutnya dengan penjelasan dan cuplikan kode.
Anda juga dapat mempertimbangkan opsi alternatif:
- hidrasi parsial dengan Preact dan Eleventy,
- hidrasi progresif dalam repo React GitHub,
- hidrasi malas di Vue.js (repo GitHub),
- Impor Pola Interaksi ke sumber daya non-kritis yang lambat dimuat (misalnya komponen, penyematan) saat pengguna berinteraksi dengan UI yang membutuhkannya.
Jason Miller telah menerbitkan demo kerja tentang bagaimana hidrasi progresif dapat diimplementasikan dengan React, sehingga Anda dapat langsung menggunakannya: demo 1, demo 2, demo 3 (juga tersedia di GitHub). Plus, Anda dapat melihat ke perpustakaan komponen reaksi-prarender.
- Sudahkah kita mengoptimalkan strategi untuk React/SPA?
Berjuang dengan kinerja di aplikasi aplikasi satu halaman Anda? Jeremy Wagner telah mengeksplorasi dampak kinerja kerangka kerja sisi klien pada berbagai perangkat, menyoroti beberapa implikasi dan pedoman yang mungkin ingin kami ketahui saat menggunakannya.Akibatnya, inilah strategi SPA yang disarankan Jeremy untuk digunakan untuk kerangka kerja React (tetapi seharusnya tidak berubah secara signifikan untuk kerangka kerja lain):
- Refactor komponen stateful sebagai komponen stateless bila memungkinkan.
- Prarender komponen stateless jika memungkinkan untuk meminimalkan waktu respons server. Render hanya di server.
- Untuk komponen stateful dengan interaktivitas sederhana, pertimbangkan untuk melakukan prarender atau server-rendering komponen tersebut, dan ganti interaktivitasnya dengan event listener yang tidak bergantung pada kerangka kerja .
- Jika Anda harus menghidrasi komponen stateful pada klien, gunakan hidrasi malas pada visibilitas atau interaksi.
- Untuk komponen yang terhidrasi dengan lambat, jadwalkan hidrasinya selama waktu idle thread utama dengan
requestIdleCallback
.
Ada beberapa strategi lain yang mungkin ingin Anda kejar atau tinjau:
- Pertimbangan kinerja untuk CSS-in-JS di aplikasi React
- Kurangi Ukuran Bundel Next.js dengan memuat polyfill hanya jika diperlukan, menggunakan impor dinamis dan hidrasi lambat.
- Rahasia JavaScript: Kisah Bereaksi, Optimalisasi Kinerja, dan Multi-threading, seri 7 bagian yang panjang tentang peningkatan tantangan antarmuka pengguna dengan React,
- Cara mengukur kinerja React dan Cara membuat profil aplikasi React.
- Membangun animasi web mobile-first di React, ceramah fantastis oleh Alex Holachek, bersama dengan slide dan repo GitHub ( terima kasih atas tipnya, Addy! ).
- webpack-libs-optimizations adalah repo GitHub yang fantastis dengan banyak pengoptimalan terkait kinerja khusus Webpack yang berguna. Dikelola oleh Ivan Akulov.
- Peningkatan kinerja React di Notion, panduan oleh Ivan Akulov tentang cara meningkatkan kinerja di React, dengan banyak petunjuk berguna untuk membuat aplikasi sekitar 30% lebih cepat.
- Plugin React Refresh Webpack (eksperimental) memungkinkan pemuatan ulang panas yang mempertahankan status komponen, dan mendukung komponen kait dan fungsi.
- Perhatikan React Server Components dengan ukuran zero-bundle, jenis komponen baru yang diusulkan yang tidak akan berdampak pada ukuran bundle. Proyek ini sedang dalam pengembangan, tetapi umpan balik dari komunitas sangat dihargai (penjelas hebat oleh Sophie Alpert).
- Apakah Anda menggunakan prefetching prefetching untuk potongan JavaScript?
Kita bisa menggunakan heuristik untuk memutuskan kapan harus memuat potongan JavaScript terlebih dahulu. Guess.js adalah seperangkat alat dan pustaka yang menggunakan data Google Analytics untuk menentukan halaman mana yang kemungkinan besar akan dikunjungi pengguna berikutnya dari halaman tertentu. Berdasarkan pola navigasi pengguna yang dikumpulkan dari Google Analytics atau sumber lain, Guess.js membuat model pembelajaran mesin untuk memprediksi dan mengambil lebih dulu JavaScript yang akan diperlukan pada setiap halaman berikutnya.Oleh karena itu, setiap elemen interaktif menerima skor probabilitas untuk keterlibatan, dan berdasarkan skor tersebut, skrip sisi klien memutuskan untuk mengambil sumber daya terlebih dahulu. Anda dapat mengintegrasikan teknik ini ke aplikasi Next.js Anda, Angular dan React, dan ada plugin Webpack yang juga mengotomatiskan proses penyiapan.
Jelas, Anda mungkin meminta browser untuk menggunakan data yang tidak diperlukan dan mengambil halaman yang tidak diinginkan sebelumnya, jadi sebaiknya berhati-hatilah dalam jumlah permintaan yang diambil sebelumnya. Kasus penggunaan yang baik adalah mengambil skrip validasi terlebih dahulu yang diperlukan di checkout, atau mengambil terlebih dahulu spekulatif saat ajakan bertindak penting masuk ke viewport.
Butuh sesuatu yang kurang canggih? DNStradamus melakukan prefetching DNS untuk tautan keluar saat muncul di viewport. Quicklink, InstantClick, dan Instant.page adalah pustaka kecil yang secara otomatis mengambil tautan di viewport selama waktu idle dalam upaya membuat navigasi halaman berikutnya memuat lebih cepat. Quicklink memungkinkan untuk mengambil terlebih dahulu rute React Router dan Javascript; selain itu hemat data, jadi tidak mengambil di 2G atau jika
Data-Saver
aktif. Begitu juga dengan Instant.page jika mode diatur untuk menggunakan prefetching viewport (yang merupakan default).Jika Anda ingin melihat ke dalam ilmu prefetching prediktif secara lengkap, Divya Tagtachian memiliki ceramah yang bagus tentang The Art of Predictive Prefetch, yang mencakup semua opsi dari awal hingga akhir.
- Manfaatkan pengoptimalan untuk mesin JavaScript target Anda.
Pelajari apa yang mendominasi mesin JavaScript di basis pengguna Anda, lalu jelajahi cara mengoptimalkannya. Misalnya, saat mengoptimalkan V8 yang digunakan di Blink-browser, runtime Node.js, dan Electron, gunakan streaming skrip untuk skrip monolitik.Streaming skrip memungkinkan
defer scripts
async
atau tunda untuk diuraikan pada utas latar belakang yang terpisah setelah pengunduhan dimulai, karenanya dalam beberapa kasus meningkatkan waktu pemuatan halaman hingga 10%. Practically, use<script defer>
in the<head>
, so that the browsers can discover the resource early and then parse it on the background thread.Caveat : Opera Mini doesn't support script deferment, so if you are developing for India or Africa,
defer
will be ignored, resulting in blocking rendering until the script has been evaluated (thanks Jeremy!) .You could also hook into V8's code caching as well, by splitting out libraries from code using them, or the other way around, merge libraries and their uses into a single script, group small files together and avoid inline scripts. Or perhaps even use v8-compile-cache.
When it comes to JavaScript in general, there are also some practices that are worth keeping in mind:
- Clean Code concepts for JavaScript, a large collection of patterns for writing readable, reusable, and refactorable code.
- You can Compress data from JavaScript with the CompressionStream API, eg to gzip before uploading data (Chrome 80+).
- Detached window memory leaks and Fixing memory leaks in web apps are detailed guides on how to find and fix tricky JavaScript memory leaks. Plus, you can use queryObjects(SomeConstructor) from the DevTools Console ( thanks, Mathias! ).
- Reexports are bad for loading and runtime performance, and avoiding them can help reduce the bundle size significantly.
- We can improve scroll performance with passive event listeners by setting a flag in the
options
parameter. So browsers can scroll the page immediately, rather than after the listener has finished. (via Kayce Basques). - If you have any
scroll
ortouch*
listeners, passpassive: true
to addEventListener. This tells the browser you're not planning to callevent.preventDefault()
inside, so it can optimize the way it handles these events. (via Ivan Akulov) - We can achieve better JavaScript scheduling with isInputPending(), a new API that attempts to bridge the gap between loading and responsiveness with the concepts of interrupts for user inputs on the web, and allows for JavaScript to be able to check for input without yielding to the browser.
- You can also automatically remove an event listener after it has executed.
- Firefox's recently released Warp, a significant update to SpiderMonkey (shipped in Firefox 83), Baseline Interpreter and there are a few JIT Optimization Strategies available as well.
- Always prefer to self-host third-party assets.
Yet again, self-host your static assets by default. It's common to assume that if many sites use the same public CDN and the same version of a JavaScript library or a web font, then the visitors would land on our site with the scripts and fonts already cached in their browser, speeding up their experience considerably. However, it's very unlikely to happen.For security reasons, to avoid fingerprinting, browsers have been implementing partitioned caching that was introduced in Safari back in 2013, and in Chrome last year. So if two sites point to the exact same third-party resource URL, the code is downloaded once per domain , and the cache is "sandboxed" to that domain due to privacy implications ( thanks, David Calhoun! ). Hence, using a public CDN will not automatically lead to better performance.
Furthermore, it's worth noting that resources don't live in the browser's cache as long as we might expect, and first-party assets are more likely to stay in the cache than third-party assets. Therefore, self-hosting is usually more reliable and secure, and better for performance, too.
- Constrain the impact of third-party scripts.
With all performance optimizations in place, often we can't control third-party scripts coming from business requirements. Third-party-scripts metrics aren't influenced by end-user experience, so too often one single script ends up calling a long tail of obnoxious third-party scripts, hence ruining a dedicated performance effort. To contain and mitigate performance penalties that these scripts bring along, it's not enough to just defer their loading and execution and warm up connections via resource hints, iedns-prefetch
orpreconnect
.Currently 57% of all JavaScript code excution time is spent on third-party code. The median mobile site accesses 12 third-party domains , with a median of 37 different requests (or about 3 requests made to each third party).
Furthermore, these third-parties often invite fourth-party scripts to join in, ending up with a huge performance bottleneck, sometimes going as far as to the eigth-party scripts on a page. So regularly auditing your dependencies and tag managers can bring along costly surprises.
Another problem, as Yoav Weiss explained in his talk on third-party scripts, is that in many cases these scripts download resources that are dynamic. The resources change between page loads, so we don't necessarily know which hosts the resources will be downloaded from and what resources they would be.
Deferring, as shown above, might be just a start though as third-party scripts also steal bandwidth and CPU time from your app. We could be a bit more aggressive and load them only when our app has initialized.
/* Before */ const App = () => { return <div> <script> window.dataLayer = window.dataLayer || []; function gtag(){...} gtg('js', new Date()); </script> </div> } /* After */ const App = () => { const[isRendered, setRendered] = useState(false); useEffect(() => setRendered(true)); return <div> {isRendered ? <script> window.dataLayer = window.dataLayer || []; function gtag(){...} gtg('js', new Date()); </script> : null} </div> }
In a fantastic post on "Reducing the Site-Speed Impact of Third-Party Tags", Andy Davies explores a strategy of minimizing the footprint of third-parties — from identifying their costs towards reducing their impact.
According to Andy, there are two ways tags impact site-speed — they compete for network bandwidth and processing time on visitors' devices, and depending on how they're implemented, they can delay HTML parsing as well. So the first step is to identify the impact that third-parties have, by testing the site with and without scripts using WebPageTest. With Simon Hearne's Request Map, we can also visualize third-parties on a page along with details on their size, type and what triggered their load.
Preferably self-host and use a single hostname, but also use a request map to exposes fourth-party calls and detect when the scripts change. You can use Harry Roberts' approach for auditing third parties and produce spreadsheets like this one (also check Harry's auditing workflow).
Afterwards, we can explore lightweight alternatives to existing scripts and slowly replace duplicates and main culprits with lighter options. Perhaps some of the scripts could be replaced with their fallback tracking pixel instead of the full tag.
If it's not viable, we can at least lazy load third-party resources with facades, ie a static element which looks similar to the actual embedded third-party, but is not functional and therefore much less taxing on the page load. The trick, then, is to load the actual embed only on interaction .
For example, we can use:
- lite-vimeo-embed for the Vimeo player,
- lite-vimeo for the Vimeo player,
- lite-youtube-embed for the YouTube player,
- react-live-chat-loader for a live chat (case study, and another case-study),
- lazyframe for iframes.
One of the reasons why tag managers are usually large in size is because of the many simultaneous experiments that are running at the same time, along with many user segments, page URLs, sites etc., so according to Andy, reducing them can reduce both the download size and the time it takes to execute the script in the browser.
And then there are anti-flicker snippets. Third-parties such as Google Optimize, Visual Web Optimizer (VWO) and others are unanimous in using them. These snippets are usually injected along with running A/B tests : to avoid flickering between the different test scenarios, they hide the
body
of the document withopacity: 0
, then adds a function that gets called after a few seconds to bring theopacity
back. This often results in massive delays in rendering due to massive client-side execution costs.Therefore keep track how often the anti-flicker timeout is triggered and reduce the timeout. Default blocks display of your page by up to 4s which will ruin conversion rates. According to Tim Kadlec, "Friends don't let friends do client side A/B testing". Server-side A/B testing on CDNs (eg Edge Computing, or Edge Slice Rerendering) is always a more performant option.
If you have to deal with almighty Google Tag Manager , Barry Pollard provides some guidelines to contain the impact of Google Tag Manager. Also, Christian Schaefer explores strategies for loading ads.
Hati-hati: beberapa widget pihak ketiga menyembunyikan diri dari alat audit, sehingga mungkin lebih sulit dikenali dan diukur. Untuk menguji pihak ketiga, periksa ringkasan bottom-up di halaman Profil kinerja di DevTools, uji apa yang terjadi jika permintaan diblokir atau telah habis waktu — untuk yang terakhir, Anda dapat menggunakan server Blackhole WebPageTest
blackhole.webpagetest.org
yang Anda dapat mengarahkan domain tertentu ke dalam filehosts
Anda.Pilihan apa yang kita miliki saat itu? Pertimbangkan untuk menggunakan pekerja layanan dengan mempercepat unduhan sumber daya dengan batas waktu dan jika sumber daya tidak merespons dalam batas waktu tertentu, kembalikan respons kosong untuk memberi tahu browser untuk melanjutkan penguraian halaman. Anda juga dapat mencatat atau memblokir permintaan pihak ketiga yang tidak berhasil atau tidak memenuhi kriteria tertentu. Jika Anda bisa, muat skrip pihak ke-3 dari server Anda sendiri daripada dari server vendor dan muat lambat.
Pilihan lainnya adalah menetapkan Kebijakan Keamanan Konten (CSP) untuk membatasi dampak skrip pihak ketiga, misalnya melarang pengunduhan audio atau video. Opsi terbaik adalah menyematkan skrip melalui
<iframe>
sehingga skrip berjalan dalam konteks iframe dan karenanya tidak memiliki akses ke DOM halaman, dan tidak dapat menjalankan kode arbitrer di domain Anda. Iframe dapat dibatasi lebih lanjut menggunakan atributsandbox
, sehingga Anda dapat menonaktifkan fungsionalitas apa pun yang mungkin dilakukan iframe, misalnya mencegah skrip berjalan, mencegah peringatan, pengiriman formulir, plugin, akses ke navigasi teratas, dan sebagainya.Anda juga dapat mengawasi pihak ketiga melalui linting kinerja dalam browser dengan kebijakan fitur, fitur yang relatif baru yang memungkinkan Anda
memilih masuk atau keluar dari fitur browser tertentu di situs Anda. (Sebagai catatan tambahan, ini juga dapat digunakan untuk menghindari gambar yang terlalu besar dan tidak dioptimalkan, media yang tidak berukuran, skrip sinkronisasi, dan lainnya). Saat ini didukung di browser berbasis Blink. /* Via Tim Kadlec. https://timkadlec.com/remembers/2020-02-20-in-browser-performance-linting-with-feature-policies/ */ /* Block the use of the Geolocation API with a Feature-Policy header. */ Feature-Policy: geolocation 'none'
/* Via Tim Kadlec. https://timkadlec.com/remembers/2020-02-20-in-browser-performance-linting-with-feature-policies/ */ /* Block the use of the Geolocation API with a Feature-Policy header. */ Feature-Policy: geolocation 'none'
Karena banyak skrip pihak ketiga yang berjalan di iframe, Anda mungkin perlu berhati-hati dalam membatasi kelonggarannya. Iframe kotak pasir selalu merupakan ide yang bagus, dan setiap batasan dapat dihilangkan melalui sejumlah nilai yang
allow
pada atributsandbox
. Sandboxing didukung hampir di semua tempat, jadi batasi skrip pihak ketiga seminimal mungkin.Pertimbangkan untuk menggunakan Pengamat Persimpangan; yang akan memungkinkan iklan dibingkai saat masih mengirimkan acara atau mendapatkan informasi yang mereka butuhkan dari DOM (mis. keterlihatan iklan). Waspadai kebijakan baru seperti Kebijakan fitur, batas ukuran sumber daya, dan prioritas CPU/Bandwidth untuk membatasi fitur web berbahaya dan skrip yang akan memperlambat browser, misalnya skrip sinkron, permintaan XHR sinkron, document.write , dan implementasi usang.
Terakhir, saat memilih layanan pihak ketiga, pertimbangkan untuk memeriksa ThirdPartyWeb.Today milik Patrick Hulce, layanan yang mengelompokkan semua skrip pihak ketiga berdasarkan kategori (analitik, sosial, periklanan, hosting, pengelola tag, dll.) dan memvisualisasikan berapa lama skrip entitas ambil untuk dieksekusi (rata-rata). Jelas, entitas terbesar memiliki dampak kinerja terburuk pada halaman tempat mereka berada. Hanya dengan membaca sekilas halaman, Anda akan mendapatkan gambaran tentang jejak kinerja yang seharusnya Anda harapkan.
Ah, dan jangan lupa tentang tersangka yang biasa: alih-alih widget pihak ketiga untuk berbagi, kita dapat menggunakan tombol berbagi sosial statis (seperti oleh SSBG) dan tautan statis ke peta interaktif alih-alih peta interaktif.
- Setel header cache HTTP dengan benar.
Caching tampaknya merupakan hal yang jelas untuk dilakukan, namun mungkin cukup sulit untuk melakukannya dengan benar. Kita perlu memeriksa ulang bahwaexpires
,max-age
,cache-control
, dan header cache HTTP lainnya telah disetel dengan benar. Tanpa header cache HTTP yang tepat, browser akan menyetelnya secara otomatis pada 10% dari waktu yang telah berlalu sejaklast-modified
, yang berakhir dengan potensi under- dan over-caching.Secara umum, sumber daya harus dapat disimpan dalam cache baik untuk waktu yang sangat singkat (jika cenderung berubah) atau tanpa batas waktu (jika statis) — Anda dapat mengubah versinya di URL bila diperlukan. Anda dapat menyebutnya sebagai strategi Cache-Forever, di mana kami dapat menyampaikan header
Cache-Control
danExpires
ke browser untuk hanya mengizinkan aset kedaluwarsa dalam setahun. Oleh karena itu, browser bahkan tidak akan membuat permintaan untuk aset jika ada di cache.Pengecualiannya adalah respons API (mis
/api/user
). Untuk mencegah caching, kita bisa menggunakanprivate, no store
, dan notmax-age=0, no-store
:Cache-Control: private, no-store
Gunakan
Cache-control: immutable
untuk menghindari validasi ulang dari masa pakai cache eksplisit yang panjang saat pengguna menekan tombol muat ulang. Untuk kasus reload, permintaan HTTP yangimmutable
menyimpan dan meningkatkan waktu buka HTML dinamis karena tidak lagi bersaing dengan banyak 304 tanggapan.Contoh umum di mana kami ingin menggunakan yang tidak dapat
immutable
adalah aset CSS/JavaScript dengan hash di namanya. Bagi mereka, kami mungkin ingin melakukan cache selama mungkin, dan memastikan mereka tidak pernah divalidasi ulang:Cache-Control: max-age: 31556952, immutable
Menurut penelitian Colin Bendell,
immutable
mengurangi 304 pengalihan sekitar 50% karena bahkan denganmax-age
digunakan, klien masih memvalidasi ulang dan memblokir setelah penyegaran. Ini didukung di Firefox, Edge dan Safari dan Chrome masih memperdebatkan masalah ini.Menurut Web Almanac, "penggunaannya telah berkembang menjadi 3,5%, dan banyak digunakan di Facebook dan tanggapan pihak ketiga Google."
Apakah Anda ingat yang baik 'basi-sementara-validasi ulang? Saat kita menentukan waktu caching dengan header respons
Cache-Control
(misCache-Control: max-age=604800
), setelahmax-age
kedaluwarsa, browser akan mengambil kembali konten yang diminta, menyebabkan halaman dimuat lebih lambat. Perlambatan ini dapat dihindari denganstale-while-revalidate
; itu pada dasarnya mendefinisikan jendela waktu tambahan di mana cache dapat menggunakan aset basi selama itu memvalidasi ulang async di latar belakang. Dengan demikian, ia "menyembunyikan" latensi (baik di jaringan maupun di server) dari klien.Pada Juni–Juli 2019, Chrome dan Firefox meluncurkan dukungan
stale-while-revalidate
di header HTTP Cache-Control, sehingga sebagai hasilnya, ini akan meningkatkan latensi pemuatan halaman berikutnya karena aset basi tidak lagi berada di jalur kritis. Hasil: nol RTT untuk tampilan berulang.Berhati-hatilah dengan tajuk bervariasi, terutama yang terkait dengan CDN, dan waspadai Varian Representasi HTTP yang membantu menghindari perjalanan pulang pergi tambahan untuk validasi setiap kali permintaan baru sedikit berbeda (tetapi tidak signifikan) dari permintaan sebelumnya ( terima kasih, Guy and Mark ! ).
Juga, periksa kembali apakah Anda tidak mengirim tajuk yang tidak perlu (mis
x-powered-by
,pragma
,x-ua-compatible
,expires
,X-XSS-Protection
, dan lainnya) dan Anda menyertakan tajuk keamanan dan kinerja yang berguna (seperti sebagaiContent-Security-Policy
,X-Content-Type-Options
dan lainnya). Terakhir, ingatlah biaya kinerja permintaan CORS dalam aplikasi satu halaman.Catatan : Kami sering berasumsi bahwa aset yang di-cache diambil secara instan, tetapi penelitian menunjukkan bahwa mengambil objek dari cache dapat memakan waktu ratusan milidetik. Bahkan, menurut Simon Hearne, "terkadang jaringan mungkin lebih cepat daripada cache, dan mengambil aset dari cache bisa mahal dengan sejumlah besar aset yang di-cache (bukan ukuran file) dan perangkat pengguna. Misalnya: rata-rata pengambilan cache Chrome OS menggandakan dari ~50ms dengan 5 sumber daya yang di-cache hingga ~100ms dengan 25 sumber daya".
Selain itu, kami sering berasumsi bahwa ukuran bundel bukanlah masalah besar dan pengguna akan mengunduhnya sekali dan kemudian menggunakan versi yang di-cache. Pada saat yang sama, dengan CI/CD kami mendorong kode ke produksi beberapa kali sehari, cache menjadi tidak valid setiap saat, jadi menjadi strategis tentang masalah caching.
Dalam hal caching, ada banyak sumber daya yang layak dibaca:
- Cache-Control for Civilians, menyelami semua caching dengan Harry Roberts.
- Primer Heroku pada header caching HTTP,
- Praktik Terbaik Caching oleh Jake Archibald,
- Primer caching HTTP oleh Ilya Grigorik,
- Menjaga segala sesuatunya tetap segar dengan basi-sementara-validasi ulang oleh Jeff Posnick.
- CS Divisualisasikan: CORS oleh Lydia Hallie adalah penjelas hebat tentang CORS, cara kerjanya dan cara memahaminya.
- Berbicara tentang CORS, inilah sedikit penyegaran tentang Kebijakan Same-Origin oleh Eric Portis.
Pengoptimalan Pengiriman
- Apakah kita menggunakan
defer
untuk memuat JavaScript penting secara asinkron?
Saat pengguna meminta halaman, browser mengambil HTML dan membuat DOM, lalu mengambil CSS dan membuat CSSOM, lalu membuat pohon rendering dengan mencocokkan DOM dan CSSOM. Jika ada JavaScript yang perlu diselesaikan, browser tidak akan mulai merender halaman sampai diselesaikan, sehingga menunda rendering. Sebagai pengembang, kita harus secara eksplisit memberi tahu browser untuk tidak menunggu dan mulai merender halaman. Cara melakukan ini untuk skrip adalah dengan atributdefer
danasync
dalam HTML.Dalam praktiknya, ternyata lebih baik menggunakan
defer
daripadaasync
. Ah, apa bedanya lagi? Menurut Steve Souders, begitu skripasync
tiba, skrip tersebut segera dieksekusi — segera setelah skrip siap. Jika itu terjadi sangat cepat, misalnya ketika skrip berada di cache aleady, itu sebenarnya dapat memblokir parser HTML. Dengandefer
, browser tidak menjalankan skrip sampai HTML diuraikan. Jadi, kecuali Anda membutuhkan JavaScript untuk dieksekusi sebelum memulai render, lebih baik menggunakandefer
. Selain itu, beberapa file async akan dieksekusi dalam urutan yang tidak deterministik.Perlu dicatat bahwa ada beberapa kesalahpahaman tentang
async
dandefer
. Yang terpenting,async
tidak berarti bahwa kode akan berjalan setiap kali skrip siap; itu berarti itu akan berjalan setiap kali skrip siap dan semua pekerjaan sinkronisasi sebelumnya selesai. Dalam kata-kata Harry Roberts, "Jika Anda meletakkan skripasync
setelah skrip sinkronisasi, skripasync
Anda hanya secepat skrip sinkronisasi paling lambat Anda."Juga, tidak disarankan untuk menggunakan
async
dandefer
. Peramban modern mendukung keduanya, tetapi setiap kali kedua atribut digunakan,async
akan selalu menang.Jika Anda ingin mempelajari lebih detail, Milica Mihajlija telah menulis panduan yang sangat mendetail tentang Membangun DOM lebih cepat, membahas detail parsing spekulatif, asinkron, dan penangguhan.
- Lazy memuat komponen mahal dengan IntersectionObserver dan petunjuk prioritas.
Secara umum, disarankan untuk memuat lambat semua komponen mahal, seperti JavaScript yang berat, video, iframe, widget, dan kemungkinan gambar. Pemuatan lambat bawaan sudah tersedia untuk gambar dan iframe dengan atributloading
(hanya Chromium). Di bawah tenda, atribut ini menunda pemuatan sumber daya hingga mencapai jarak yang dihitung dari area pandang.<!-- Lazy loading for images, iframes, scripts. Probably for images outside of the viewport. --> <img loading="lazy" ... /> <iframe loading="lazy" ... /> <!-- Prompt an early download of an asset. For critical images, eg hero images. --> <img loading="eager" ... /> <iframe loading="eager" ... />
Ambang batas itu bergantung pada beberapa hal, mulai dari jenis sumber daya gambar yang diambil hingga jenis koneksi yang efektif. Namun eksperimen yang dilakukan menggunakan Chrome di Android menunjukkan bahwa pada 4G, 97,5% gambar paruh bawah yang dimuat lambat dimuat penuh dalam waktu 10 mdtk setelah terlihat, jadi gambar tersebut seharusnya aman.
Kita juga dapat menggunakan atribut
importance
(high
ataulow
) pada elemen<script>
,<img>
, atau<link>
(hanya Blink). Faktanya, ini adalah cara yang bagus untuk mengurangi prioritas gambar di carousel, serta memprioritaskan ulang skrip. Namun, terkadang kita mungkin memerlukan kontrol yang lebih terperinci.<!-- When the browser assigns "High" priority to an image, but we don't actually want that. --> <img src="less-important-image.svg" importance="low" ... /> <!-- We want to initiate an early fetch for a resource, but also deprioritize it. --> <link rel="preload" importance="low" href="/script.js" as="script" />
Cara paling berperforma untuk melakukan pemuatan lambat yang sedikit lebih canggih adalah dengan menggunakan Intersection Observer API yang menyediakan cara untuk mengamati perubahan secara asinkron di persimpangan elemen target dengan elemen ancestor atau dengan viewport dokumen tingkat atas. Pada dasarnya, Anda perlu membuat objek
IntersectionObserver
baru, yang menerima fungsi panggilan balik dan serangkaian opsi. Kemudian kita tambahkan target untuk diamati.Fungsi callback dijalankan saat target menjadi terlihat atau tidak terlihat, jadi saat memotong area pandang, Anda dapat mulai mengambil beberapa tindakan sebelum elemen terlihat. Faktanya, kami memiliki kontrol granular kapan panggilan balik pengamat harus dipanggil, dengan
rootMargin
(margin di sekitar root) danthreshold
(satu nomor atau larik angka yang menunjukkan berapa persentase visibilitas target yang kami tuju).Alejandro Garcia Anglada telah menerbitkan tutorial praktis tentang cara menerapkannya, Rahul Nanwani menulis posting terperinci tentang pemuatan lambat gambar latar depan dan latar belakang, dan Google Fundamentals memberikan tutorial terperinci tentang pemuatan lambat gambar dan video dengan Intersection Observer juga.
Ingat cerita yang diarahkan seni membaca panjang dengan benda bergerak dan lengket? Anda juga dapat mengimplementasikan scrollytelling dengan Intersection Observer.
Periksa lagi apa lagi yang bisa Anda muat dengan malas. Bahkan string terjemahan dan emoji yang memuat lambat dapat membantu. Dengan demikian, Mobile Twitter berhasil mencapai eksekusi JavaScript 80% lebih cepat dari jalur internasionalisasi baru.
Namun, peringatan singkat: perlu dicatat bahwa pemuatan lambat harus menjadi pengecualian daripada aturan. Mungkin tidak masuk akal untuk malas memuat apa pun yang sebenarnya Anda ingin orang lihat dengan cepat, misalnya gambar halaman produk, gambar pahlawan, atau skrip yang diperlukan agar navigasi utama menjadi interaktif.
- Muat gambar secara bertahap.
Anda bahkan dapat melakukan pemuatan lambat ke tingkat berikutnya dengan menambahkan pemuatan gambar progresif ke halaman Anda. Sama halnya dengan Facebook, Pinterest, Medium, dan Wolt, Anda dapat memuat gambar berkualitas rendah atau bahkan buram terlebih dahulu, lalu saat halaman terus dimuat, gantilah dengan versi kualitas penuh dengan menggunakan teknik BlurHash atau LQIP (Low Quality Image Placeholder) teknik.Pendapat berbeda jika teknik ini meningkatkan pengalaman pengguna atau tidak, tetapi itu pasti meningkatkan waktu untuk First Contentful Paint. Kami bahkan dapat mengotomatiskannya dengan menggunakan SQIP yang membuat versi gambar berkualitas rendah sebagai placeholder SVG, atau Gradient Image Placeholder dengan gradien linier CSS.
Placeholder ini dapat disematkan di dalam HTML karena secara alami terkompresi dengan baik dengan metode kompresi teks. Dalam artikelnya, Dean Hume telah menjelaskan bagaimana teknik ini dapat diimplementasikan menggunakan Intersection Observer.
mundur? Jika browser tidak mendukung pengamat persimpangan, kita masih bisa malas memuat polyfill atau segera memuat gambar. Dan bahkan ada perpustakaan untuk itu.
Ingin menjadi lebih mewah? Anda dapat melacak gambar Anda dan menggunakan bentuk dan tepi primitif untuk membuat placeholder SVG yang ringan, memuatnya terlebih dahulu, lalu bertransisi dari gambar vektor placeholder ke gambar bitmap (dimuat).
- Apakah Anda menunda rendering dengan
content-visibility
?
Untuk tata letak yang kompleks dengan banyak blok konten, gambar, dan video, decoding data dan rendering piksel mungkin merupakan operasi yang cukup mahal — terutama pada perangkat kelas bawah. Dengancontent-visibility: auto
, kita dapat meminta browser untuk melewati tata letak anak-anak saat wadah berada di luar viewport.Misalnya, Anda mungkin melewatkan rendering footer dan bagian akhir pada pemuatan awal:
footer { content-visibility: auto; contain-intrinsic-size: 1000px; /* 1000px is an estimated height for sections that are not rendered yet. */ }
Perhatikan bahwa visibilitas konten: otomatis; berperilaku seperti overflow: hidden; , tetapi Anda dapat memperbaikinya dengan menerapkan
padding-left
danpadding-right
sebagai ganti defaultmargin-left: auto;
,margin-right: auto;
dan lebar yang dinyatakan. Padding pada dasarnya memungkinkan elemen meluap ke kotak konten dan masuk ke kotak padding tanpa meninggalkan model kotak secara keseluruhan dan terpotong.Juga, perlu diingat bahwa Anda mungkin memperkenalkan beberapa CLS saat konten baru akhirnya dirender, jadi sebaiknya gunakan
contain-intrinsic-size
pengganti yang tepat ( terima kasih, Una! ).Thijs Terluin memiliki lebih banyak detail tentang kedua properti dan bagaimana
contain-intrinsic-size
konten dihitung oleh browser, Malte Ubl menunjukkan bagaimana Anda dapat menghitungnya dan penjelasan video singkat oleh Jake dan Surma menjelaskan cara kerjanya.Dan jika Anda perlu sedikit lebih terperinci, dengan CSS Containment, Anda dapat secara manual melewati pekerjaan tata letak, gaya, dan pengecatan untuk turunan simpul DOM jika Anda hanya memerlukan ukuran, perataan, atau gaya yang dihitung pada elemen lain — atau elemen tersebut saat ini di luar kanvas.
- Apakah Anda menunda decoding dengan
decoding="async"
?
Terkadang konten muncul di luar layar, namun kami ingin memastikan bahwa konten tersedia saat pelanggan membutuhkannya — idealnya, tidak memblokir apa pun di jalur kritis, tetapi mendekode dan merender secara asinkron. Kita dapat menggunakandecoding="async"
untuk memberikan izin kepada browser untuk memecahkan kode gambar dari utas utama, menghindari dampak pengguna dari waktu CPU yang digunakan untuk memecahkan kode gambar (melalui Malte Ubl):<img decoding="async" … />
Atau, untuk gambar di luar layar, kita dapat menampilkan placeholder terlebih dahulu, dan ketika gambar berada di dalam viewport, menggunakan IntersectionObserver, memicu panggilan jaringan agar gambar diunduh di latar belakang. Selain itu, kita dapat menunda render hingga decode dengan img.decode() atau mengunduh gambar jika Image Decode API tidak tersedia.
Saat merender gambar, kita dapat menggunakan animasi fade-in, misalnya. Katie Hempenius dan Addy Osmani berbagi lebih banyak wawasan dalam pembicaraan mereka Speed at Scale: Web Performance Tips and Tricks from the Trenches.
- Apakah Anda membuat dan menyajikan CSS penting?
Untuk memastikan bahwa browser mulai merender halaman Anda secepat mungkin, sudah menjadi praktik umum untuk mengumpulkan semua CSS yang diperlukan untuk mulai merender bagian halaman pertama yang terlihat (dikenal sebagai "CSS kritis" atau "CSS paruh atas" ") dan sertakan sebaris di<head>
halaman, sehingga mengurangi perjalanan pulang pergi. Karena terbatasnya ukuran paket yang dipertukarkan selama fase slow start, anggaran Anda untuk CSS penting adalah sekitar 14 KB.Jika Anda melampaui itu, browser akan membutuhkan bolak-balik tambahan untuk mengambil lebih banyak gaya. CriticalCSS dan Critical memungkinkan Anda untuk menampilkan CSS penting untuk setiap template yang Anda gunakan. Dalam pengalaman kami, tidak ada sistem otomatis yang lebih baik daripada pengumpulan manual CSS penting untuk setiap template, dan memang itulah pendekatan yang telah kami pindahkan baru-baru ini.
Anda kemudian dapat memasukkan CSS kritis dan memuat sisanya dengan plugin critters Webpack. Jika memungkinkan, pertimbangkan untuk menggunakan pendekatan inlining bersyarat yang digunakan oleh Filament Group, atau ubah kode inline menjadi aset statis dengan cepat.
Jika saat ini Anda memuat CSS lengkap Anda secara asinkron dengan pustaka seperti loadCSS, itu tidak terlalu diperlukan. Dengan
media="print"
, Anda dapat mengelabui browser agar mengambil CSS secara asinkron tetapi menerapkan ke lingkungan layar setelah dimuat. ( terima kasih, Scott! )<!-- Via Scott Jehl. https://www.filamentgroup.com/lab/load-css-simpler/ --> <!-- Load CSS asynchronously, with low priority --> <link rel="stylesheet" href="full.css" media="print" onload="this.media='all'" />
Saat mengumpulkan semua CSS penting untuk setiap template, biasanya menjelajahi area "paro atas" saja. Namun, untuk tata letak yang kompleks, mungkin ide yang baik untuk menyertakan dasar tata letak juga untuk menghindari perhitungan ulang besar-besaran dan biaya pengecatan ulang, akibatnya merugikan skor Data Vital Web Inti Anda.
Bagaimana jika pengguna mendapatkan URL yang tertaut langsung ke tengah halaman tetapi CSS belum diunduh? Dalam hal ini, telah menjadi umum untuk menyembunyikan konten yang tidak penting, misalnya dengan
opacity: 0;
dalam CSS sebaris danopacity: 1
dalam file CSS lengkap, dan tampilkan saat CSS tersedia. Ini memiliki kelemahan utama , karena pengguna dengan koneksi lambat mungkin tidak akan pernah bisa membaca konten halaman. Itulah mengapa lebih baik untuk selalu menjaga konten tetap terlihat, meskipun mungkin tidak ditata dengan benar.Menempatkan CSS penting (dan aset penting lainnya) dalam file terpisah di domain root memiliki manfaat, kadang-kadang bahkan lebih dari inlining, karena caching. Chrome secara spekulatif membuka koneksi HTTP kedua ke domain root saat meminta halaman, yang menghilangkan kebutuhan akan koneksi TCP untuk mengambil CSS ini. Itu berarti Anda dapat membuat satu set file -CSS kritis (mis . critical-homepage.css , critical-product-page.css, dll.) dan menyajikannya dari root Anda, tanpa harus membuat inline. ( terima kasih, Filipus! )
Sebuah kata peringatan: dengan HTTP/2, CSS penting dapat disimpan dalam file CSS terpisah dan dikirimkan melalui server push tanpa membengkakkan HTML. Tangkapannya adalah bahwa mendorong server merepotkan dengan banyak gotcha dan kondisi balapan di seluruh browser. Itu tidak pernah didukung secara konsisten dan memiliki beberapa masalah caching (lihat slide 114 dan seterusnya dari presentasi Hooman Beheshti).
Efeknya, pada kenyataannya, bisa menjadi negatif dan membuat buffer jaringan membengkak, mencegah pengiriman bingkai asli dalam dokumen. Jadi tidak terlalu mengejutkan bahwa untuk saat ini, Chrome berencana untuk menghapus dukungan untuk Server Push.
- Bereksperimenlah dengan mengelompokkan kembali aturan CSS Anda.
Kami telah terbiasa dengan CSS penting, tetapi ada beberapa pengoptimalan yang dapat melampaui itu. Harry Roberts melakukan penelitian yang luar biasa dengan hasil yang cukup mengejutkan. Misalnya, mungkin ide yang baik untuk membagi file CSS utama menjadi kueri media individualnya. Dengan begitu, browser akan mengambil CSS penting dengan prioritas tinggi, dan semua hal lain dengan prioritas rendah — sepenuhnya keluar dari jalur kritis.Juga, hindari menempatkan
<link rel="stylesheet" />
sebelumasync
snippet. Jika skrip tidak bergantung pada stylesheet, pertimbangkan untuk menempatkan skrip pemblokiran di atas gaya pemblokiran. Jika ya, pisahkan JavaScript itu menjadi dua dan muat di kedua sisi CSS Anda.Scott Jehl memecahkan masalah menarik lainnya dengan men-cache file CSS sebaris dengan pekerja layanan, masalah umum yang biasa terjadi jika Anda menggunakan CSS kritis. Pada dasarnya, kami menambahkan atribut ID ke elemen
style
sehingga mudah ditemukan menggunakan JavaScript, kemudian sebagian kecil JavaScript menemukan CSS itu dan menggunakan Cache API untuk menyimpannya di cache browser lokal (dengan tipe kontentext/css
) untuk digunakan pada halaman berikutnya. Untuk menghindari inlining pada halaman berikutnya dan sebagai gantinya mereferensikan aset yang di-cache secara eksternal, kami kemudian menyetel cookie pada kunjungan pertama ke sebuah situs. Voila!Perlu dicatat bahwa gaya dinamis juga bisa mahal, tetapi biasanya hanya jika Anda mengandalkan ratusan komponen yang dirender secara bersamaan. Jadi, jika Anda menggunakan CSS-in-JS, pastikan pustaka CSS-in-JS Anda mengoptimalkan eksekusi saat CSS Anda tidak memiliki ketergantungan pada tema atau props, dan jangan terlalu banyak membuat komponen bergaya . Aggelos Arvanitakis membagikan lebih banyak wawasan tentang biaya kinerja CSS-in-JS.
- Apakah Anda mengalirkan tanggapan?
Sering dilupakan dan diabaikan, stream menyediakan antarmuka untuk membaca atau menulis potongan data yang tidak sinkron, hanya sebagian yang mungkin tersedia di memori pada waktu tertentu. Pada dasarnya, mereka mengizinkan halaman yang membuat permintaan asli untuk mulai bekerja dengan respons segera setelah potongan data pertama tersedia, dan menggunakan parser yang dioptimalkan untuk streaming untuk menampilkan konten secara progresif.Kami dapat membuat satu aliran dari berbagai sumber. Misalnya, alih-alih menyajikan shell UI kosong dan membiarkan JavaScript mengisinya, Anda dapat membiarkan service worker membuat aliran di mana shell berasal dari cache, tetapi bodynya berasal dari jaringan. Seperti yang dicatat Jeff Posnick, jika aplikasi web Anda diberdayakan oleh CMS yang server-render HTML dengan menggabungkan sebagian template, model tersebut diterjemahkan secara langsung menjadi menggunakan respons streaming, dengan logika template yang direplikasi di service worker, bukan di server Anda. Artikel The Year of Web Streams karya Jake Archibald menyoroti bagaimana tepatnya Anda dapat membangunnya. Peningkatan kinerja cukup terlihat.
Satu keuntungan penting dari streaming seluruh respons HTML adalah bahwa HTML yang dirender selama permintaan navigasi awal dapat memanfaatkan sepenuhnya pengurai HTML streaming browser. Potongan HTML yang dimasukkan ke dalam dokumen setelah halaman dimuat (seperti yang biasa terjadi pada konten yang diisi melalui JavaScript) tidak dapat memanfaatkan pengoptimalan ini.
Dukungan peramban? Masih sampai di sana dengan dukungan parsial di Chrome, Firefox, Safari dan Edge yang mendukung API dan Service Worker yang didukung di semua browser modern. Dan jika Anda merasa ingin bertualang lagi, Anda dapat memeriksa implementasi eksperimental permintaan streaming, yang memungkinkan Anda untuk mulai mengirim permintaan sambil tetap membuat badan. Tersedia di Chrome 85.
- Pertimbangkan untuk membuat komponen Anda sadar akan koneksi.
Data bisa mahal dan dengan muatan yang terus bertambah, kami harus menghormati pengguna yang memilih untuk memilih penghematan data saat mengakses situs atau aplikasi kami. Header permintaan petunjuk klien Simpan-Data memungkinkan kami untuk menyesuaikan aplikasi dan muatan untuk pengguna dengan kendala biaya dan kinerja.Bahkan, Anda dapat menulis ulang permintaan untuk gambar DPI tinggi ke gambar DPI rendah, menghapus font web, efek paralaks mewah, thumbnail pratinjau dan gulir tak terbatas, mematikan pemutaran otomatis video, mendorong server, mengurangi jumlah item yang ditampilkan dan menurunkan kualitas gambar, atau bahkan mengubah cara Anda memberikan markup. Tim Vereecke telah menerbitkan artikel yang sangat rinci tentang strategi penghindaran data yang menampilkan banyak opsi untuk menyimpan data.
Siapa yang menggunakan
save-data
, Anda mungkin bertanya-tanya? 18% pengguna Chrome Android global mengaktifkan Mode Ringan (denganSave-Data
aktif), dan jumlahnya kemungkinan akan lebih tinggi. Menurut penelitian Simon Hearne, tingkat keikutsertaan tertinggi pada perangkat yang lebih murah, tetapi ada banyak outlier. Misalnya: pengguna di Kanada memiliki tingkat keikutsertaan lebih dari 34% (dibandingkan dengan ~7% di AS) dan pengguna di flagship Samsung terbaru memiliki tingkat keikutsertaan hampir 18% secara global.Dengan mengaktifkan mode
Save-Data
, Chrome Seluler akan memberikan pengalaman yang dioptimalkan, yaitu pengalaman web yang diproksi dengan skrip yang ditangguhkan ,font-display: swap
, dan pemuatan lambat yang dipaksakan. Lebih masuk akal untuk membangun pengalaman Anda sendiri daripada mengandalkan browser untuk melakukan pengoptimalan ini.Header saat ini hanya didukung di Chromium, di Chrome versi Android, atau melalui ekstensi Penghemat Data di perangkat desktop. Terakhir, Anda juga dapat menggunakan API Informasi Jaringan untuk mengirimkan modul JavaScript yang mahal, gambar dan video beresolusi tinggi berdasarkan jenis jaringan. API Informasi Jaringan dan khususnya
navigator.connection.effectiveType
menggunakan nilaiRTT
,downlink
,effectiveType
(dan beberapa lainnya) untuk memberikan representasi koneksi dan data yang dapat ditangani pengguna.Dalam konteks ini, Max Bock berbicara tentang komponen connection-aware dan Addy Osmani berbicara tentang penyajian modul adaptif. Misalnya, dengan React, kita bisa menulis komponen yang dirender secara berbeda untuk tipe koneksi yang berbeda. Seperti yang disarankan Max, komponen
<Media />
dalam artikel berita mungkin menampilkan:-
Offline
:alt
dengan teks alternatif, -
2G
/ modesave-data
: gambar beresolusi rendah, -
3G
pada layar non-Retina: gambar resolusi menengah, -
3G
pada layar Retina: gambar Retina beresolusi tinggi, -
4G
: video HD.
Dean Hume menyediakan implementasi praktis dari logika serupa menggunakan service worker. Untuk video, kami dapat menampilkan poster video secara default, lalu menampilkan ikon "Putar" serta cangkang pemutar video, meta-data video, dll. pada koneksi yang lebih baik. Sebagai cadangan untuk browser yang tidak mendukung, kita dapat mendengarkan acara
canplaythrough
dan menggunakanPromise.race()
untuk menghentikan waktu pemuatan sumber jika acaracanplaythrough
tidak diaktifkan dalam 2 detik.Jika Anda ingin menyelam lebih dalam, berikut adalah beberapa sumber untuk memulai:
- Addy Osmani menunjukkan cara mengimplementasikan penyajian adaptif di React.
- React Adaptive Loading Hooks & Utilities menyediakan cuplikan kode untuk React,
- Netanel Basel mengeksplorasi Komponen Connection-Aware di Angular,
- Theodore Vorilas membagikan bagaimana Melayani Komponen Adaptif Menggunakan API Informasi Jaringan di Vue bekerja.
- Umar Hansa menunjukkan cara selektif mengunduh/mengeksekusi JavaScript yang mahal.
-
- Pertimbangkan untuk membuat perangkat Anda sadar memori.
Koneksi jaringan memberi kita hanya satu perspektif pada konteks pengguna sekalipun. Lebih jauh, Anda juga dapat menyesuaikan sumber daya secara dinamis berdasarkan memori perangkat yang tersedia, dengan Device Memory API.navigator.deviceMemory
returns how much RAM the device has in gigabytes, rounded down to the nearest power of two. The API also features a Client Hints Header,Device-Memory
, that reports the same value.Bonus : Umar Hansa shows how to defer expensive scripts with dynamic imports to change the experience based on device memory, network connectivity and hardware concurrency.
- Warm up the connection to speed up delivery.
Use resource hints to save time ondns-prefetch
(which performs a DNS lookup in the background),preconnect
(which asks the browser to start the connection handshake (DNS, TCP, TLS) in the background),prefetch
(which asks the browser to request a resource) andpreload
(which prefetches resources without executing them, among other things). Well supported in modern browsers, with support coming to Firefox soon.Remember
prerender
? The resource hint used to prompt browser to build out the entire page in the background for next navigation. The implementations issues were quite problematic, ranging from a huge memory footprint and bandwidth usage to multiple registered analytics hits and ad impressions.Unsurprinsingly, it was deprecated, but the Chrome team has brought it back as NoState Prefetch mechanism. In fact, Chrome treats the
prerender
hint as a NoState Prefetch instead, so we can still use it today. As Katie Hempenius explains in that article, "like prerendering, NoState Prefetch fetches resources in advance ; but unlike prerendering, it does not execute JavaScript or render any part of the page in advance."NoState Prefetch only uses ~45MiB of memory and subresources that are fetched will be fetched with an
IDLE
Net Priority. Since Chrome 69, NoState Prefetch adds the header Purpose: Prefetch to all requests in order to make them distinguishable from normal browsing.Also, watch out for prerendering alternatives and portals, a new effort toward privacy-conscious prerendering, which will provide the inset
preview
of the content for seamless navigations.Using resource hints is probably the easiest way to boost performance , and it works well indeed. When to use what? As Addy Osmani has explained, it's reasonable to preload resources that we know are very likely to be used on the current page and for future navigations across multiple navigation boundaries, eg Webpack bundles needed for pages the user hasn't visited yet.
Addy's article on "Loading Priorities in Chrome" shows how exactly Chrome interprets resource hints, so once you've decided which assets are critical for rendering, you can assign high priority to them. To see how your requests are prioritized, you can enable a "priority" column in the Chrome DevTools network request table (as well as Safari).
Most of the time these days, we'll be using at least
preconnect
anddns-prefetch
, and we'll be cautious with usingprefetch
,preload
andprerender
. Note that even withpreconnect
anddns-prefetch
, the browser has a limit on the number of hosts it will look up/connect to in parallel, so it's a safe bet to order them based on priority ( thanks Philip Tellis! ).Since fonts usually are important assets on a page, sometimes it's a good idea to request the browser to download critical fonts with
preload
. However, double check if it actually helps performance as there is a puzzle of priorities when preloading fonts: aspreload
is seen as high importance, it can leapfrog even more critical resources like critical CSS. ( thanks, Barry! )<!-- Loading two rendering-critical fonts, but not all their weights. --> <!-- crossorigin="anonymous" is required due to CORS. Without it, preloaded fonts will be ignored. https://github.com/w3c/preload/issues/32 via https://twitter.com/iamakulov/status/1275790151642423303 --> <link rel="preload" as="font" href="Elena-Regular.woff2" type="font/woff2" crossorigin="anonymous" media="only screen and (min-width: 48rem)" /> <link rel="preload" as="font" href="Mija-Bold.woff2" type="font/woff2" crossorigin="anonymous" media="only screen and (min-width: 48rem)" />
<!-- Loading two rendering-critical fonts, but not all their weights. --> <!-- crossorigin="anonymous" is required due to CORS. Without it, preloaded fonts will be ignored. https://github.com/w3c/preload/issues/32 via https://twitter.com/iamakulov/status/1275790151642423303 --> <link rel="preload" as="font" href="Elena-Regular.woff2" type="font/woff2" crossorigin="anonymous" media="only screen and (min-width: 48rem)" /> <link rel="preload" as="font" href="Mija-Bold.woff2" type="font/woff2" crossorigin="anonymous" media="only screen and (min-width: 48rem)" />
Since
<link rel="preload">
accepts amedia
attribute, you could choose to selectively download resources based on@media
query rules, as shown above.Furthermore, we can use
imagesrcset
andimagesizes
attributes to preload late-discovered hero images faster, or any images that are loaded via JavaScript, eg movie posters:<!-- Addy Osmani. https://addyosmani.com/blog/preload-hero-images/ --> <link rel="preload" as="image" href="poster.jpg" image image>
<!-- Addy Osmani. https://addyosmani.com/blog/preload-hero-images/ --> <link rel="preload" as="image" href="poster.jpg" image image>
We can also preload the JSON as fetch , so it's discovered before JavaScript gets to request it:
<!-- Addy Osmani. https://addyosmani.com/blog/preload-hero-images/ --> <link rel="preload" as="fetch" href="foo.com/api/movies.json" crossorigin>
We could also load JavaScript dynamically, effectively for lazy execution of the script.
/* Adding a preload hint to the head */ var preload = document.createElement("link"); link.href = "myscript.js"; link.rel = "preload"; link.as = "script"; document.head.appendChild(link); /* Injecting a script when we want it to execute */ var script = document.createElement("script"); script.src = "myscript.js"; document.body.appendChild(script);
A few gotchas to keep in mind:
preload
is good for moving the start download time of an asset closer to the initial request, but preloaded assets land in the memory cache which is tied to the page making the request.preload
plays well with the HTTP cache: a network request is never sent if the item is already there in the HTTP cache.Hence, it's useful for late-discovered resources, hero images loaded via
background-image
, inlining critical CSS (or JavaScript) and pre-loading the rest of the CSS (or JavaScript).A
preload
tag can initiate a preload only after the browser has received the HTML from the server and the lookahead parser has found thepreload
tag. Preloading via the HTTP header could be a bit faster since we don't to wait for the browser to parse the HTML to start the request (it's debated though).Early Hints will help even further, enabling preload to kick in even before the response headers for the HTML are sent (on the roadmap in Chromium, Firefox). Plus, Priority Hints will help us indicate loading priorities for scripts.
Beware : if you're using
preload
,as
must be defined or nothing loads, plus preloaded fonts without thecrossorigin
attribute will double fetch. If you're usingprefetch
, beware of theAge
header issues in Firefox.
- Use service workers for caching and network fallbacks.
No performance optimization over a network can be faster than a locally stored cache on a user's machine (there are exceptions though). If your website is running over HTTPS, we can cache static assets in a service worker cache and store offline fallbacks (or even offline pages) and retrieve them from the user's machine, rather than going to the network.As suggested by Phil Walton, with service workers, we can send smaller HTML payloads by programmatically generating our responses. A service worker can request just the bare minimum of data it needs from the server (eg an HTML content partial, a Markdown file, JSON data, etc.), and then it can programmatically transform that data into a full HTML document. So once a user visits a site and the service worker is installed, the user will never request a full HTML page again. The performance impact can be quite impressive.
Browser support? Service workers are widely supported and the fallback is the network anyway. Does it help boost performance ? Oh yes, it does. And it's getting better, eg with Background Fetch allowing background uploads/downloads via a service worker as well.
There are a number of use cases for a service worker. For example, you could implement "Save for offline" feature, handle broken images, introduce messaging between tabs or provide different caching strategies based on request types. In general, a common reliable strategy is to store the app shell in the service worker's cache along with a few critical pages, such as offline page, frontpage and anything else that might be important in your case.
There are a few gotchas to keep in mind though. With a service worker in place, we need to beware range requests in Safari (if you are using Workbox for a service worker it has a range request module). If you ever stumbled upon
DOMException: Quota exceeded.
error in the browser console, then look into Gerardo's article When 7KB equals 7MB.Seperti yang ditulis Gerardo, “Jika Anda sedang membangun aplikasi web progresif dan mengalami penyimpanan cache yang membengkak saat pekerja layanan Anda menyimpan cache aset statis yang disajikan dari CDN, pastikan header respons CORS yang tepat ada untuk sumber daya lintas-asal, Anda tidak men-cache respons buram dengan service worker Anda secara tidak sengaja, Anda mengikutsertakan aset gambar lintas asal ke mode
crossorigin
dengan menambahkan atribut lintas asal ke tag<img>
.”Ada banyak sumber daya yang bagus untuk memulai dengan pekerja layanan:
- Service Worker Mindset, yang membantu Anda memahami cara kerja service worker di balik layar dan hal-hal yang perlu dipahami saat membangunnya.
- Chris Ferdinandi menyediakan serangkaian artikel hebat tentang service worker, menjelaskan cara membuat aplikasi offline dan mencakup berbagai skenario, mulai dari menyimpan halaman yang baru dilihat secara offline hingga menyetel tanggal kedaluwarsa untuk item di cache service worker.
- Kesalahan Service Worker dan Praktik Terbaik, dengan beberapa tips tentang cakupan, menunda pendaftaran service worker dan caching service worker.
- Seri hebat oleh Ire Aderinokun tentang "Offline First" dengan Service Worker, dengan strategi untuk mem-cache shell aplikasi.
- Service Worker: Pengantar dengan tips praktis tentang cara menggunakan service worker untuk pengalaman offline yang kaya, sinkronisasi latar belakang berkala, dan pemberitahuan push.
- Itu selalu layak mengacu pada Buku Masak Offline Jake Archibald yang bagus dengan sejumlah resep tentang cara memanggang pekerja layanan Anda sendiri.
- Workbox adalah kumpulan pustaka pekerja layanan yang dibuat khusus untuk membangun aplikasi web progresif.
- Apakah Anda menjalankan pekerja server di CDN/Edge, misalnya untuk pengujian A/B?
Pada titik ini, kami cukup terbiasa menjalankan service worker di klien, tetapi dengan CDN yang mengimplementasikannya di server, kami juga dapat menggunakannya untuk mengubah kinerja di edge.Misalnya, dalam pengujian A/B, ketika HTML perlu memvariasikan kontennya untuk pengguna yang berbeda, kita dapat menggunakan Service Worker di server CDN untuk menangani logikanya. Kami juga dapat melakukan streaming penulisan ulang HTML untuk mempercepat situs yang menggunakan Google Font.
- Optimalkan kinerja rendering.
Setiap kali aplikasi lamban, itu langsung terlihat. Jadi, kami perlu memastikan bahwa tidak ada jeda saat menggulir halaman atau saat elemen dianimasikan, dan Anda secara konsisten mencapai 60 frame per detik. Jika itu tidak memungkinkan, maka setidaknya membuat frame per detik konsisten lebih baik daripada rentang campuran 60 hingga 15. Gunakanwill-change
CSS untuk memberi tahu browser tentang elemen dan properti mana yang akan berubah.Kapan pun Anda mengalaminya, debug pengecatan ulang yang tidak perlu di DevTools:
- Ukur kinerja rendering runtime. Periksa beberapa tip berguna tentang cara memahaminya.
- Untuk memulai, lihat kursus Udacity gratis Paul Lewis tentang pengoptimalan rendering browser dan artikel Georgy Marchuk tentang pengecatan Browser dan pertimbangan untuk kinerja web.
- Aktifkan Paint Flashing di "Alat lainnya → Rendering → Paint Flashing" di Firefox DevTools.
- Di React DevTools, centang "Soroti pembaruan" dan aktifkan "Rekam mengapa setiap komponen dirender",
- Anda juga dapat menggunakan Why Did You Render, jadi saat komponen dirender ulang, flash akan memberi tahu Anda tentang perubahan tersebut.
Apakah Anda menggunakan tata letak Masonry? Perlu diingat bahwa mungkin dapat membangun tata letak Masonry dengan grid CSS saja, segera.
Jika Anda ingin menyelami topik lebih dalam, Nolan Lawson telah berbagi trik untuk mengukur kinerja tata letak secara akurat dalam artikelnya, dan Jason Miller juga menyarankan teknik alternatif. Kami juga memiliki artikel kecil oleh Sergey Chikuyonok tentang cara mendapatkan animasi GPU dengan benar.
Catatan : perubahan pada lapisan komposisi GPU adalah yang paling murah, jadi jika Anda bisa lolos dengan hanya memicu komposisi melalui
opacity
dantransform
, Anda akan berada di jalur yang benar. Anna Migas juga telah memberikan banyak saran praktis dalam ceramahnya tentang Debugging UI Rendering Performance. Dan untuk memahami cara men-debug kinerja cat di DevTools, lihat video audit Kinerja Cat Umar. - Sudahkah Anda mengoptimalkan kinerja yang dirasakan?
Meskipun urutan bagaimana komponen muncul di halaman, dan strategi bagaimana kami menyajikan aset ke browser penting, kami juga tidak boleh meremehkan peran kinerja yang dirasakan. Konsep ini berkaitan dengan aspek psikologis menunggu, pada dasarnya membuat pelanggan sibuk atau terlibat saat sesuatu yang lain sedang terjadi. Di situlah manajemen persepsi, awal preemptive, penyelesaian awal dan manajemen toleransi berperan.Apa artinya itu semua? Saat memuat aset, kami dapat mencoba untuk selalu selangkah lebih maju dari pelanggan, sehingga pengalaman terasa cepat sementara ada banyak hal yang terjadi di latar belakang. Untuk membuat pelanggan tetap terlibat, kami dapat menguji layar kerangka (demo implementasi) alih-alih memuat indikator, menambahkan transisi/animasi, dan pada dasarnya menipu UX ketika tidak ada lagi yang perlu dioptimalkan.
Dalam studi kasus mereka tentang Seni Kerangka UI, Kumar McMillan berbagi beberapa ide dan teknik tentang cara mensimulasikan daftar dinamis, teks, dan layar akhir, serta bagaimana mempertimbangkan pemikiran kerangka dengan React.
Namun berhati-hatilah: layar kerangka harus diuji sebelum digunakan karena beberapa pengujian menunjukkan bahwa layar kerangka dapat melakukan yang terburuk menurut semua metrik.
- Apakah Anda mencegah pergeseran tata letak dan pengecatan ulang?
Di ranah kinerja yang dirasakan, mungkin salah satu pengalaman yang lebih mengganggu adalah perubahan tata letak , atau reflows , yang disebabkan oleh gambar dan video yang diskalakan ulang, font web, iklan yang disuntikkan, atau skrip yang terlambat ditemukan yang mengisi komponen dengan konten sebenarnya. Akibatnya, pelanggan mungkin mulai membaca artikel hanya untuk terganggu oleh lompatan tata letak di atas area baca. Pengalamannya sering kali tiba-tiba dan cukup membingungkan: dan itu mungkin kasus pemuatan prioritas yang perlu dipertimbangkan kembali.Komunitas telah mengembangkan beberapa teknik dan solusi untuk menghindari reflows. Secara umum, sebaiknya hindari menyisipkan konten baru di atas konten yang sudah ada , kecuali jika hal itu terjadi sebagai respons terhadap interaksi pengguna. Selalu atur atribut lebar dan tinggi pada gambar, jadi browser modern mengalokasikan kotak dan memesan ruang secara default (Firefox, Chrome).
Untuk gambar atau video, kita dapat menggunakan placeholder SVG untuk memesan kotak tampilan di mana media akan muncul. Itu berarti bahwa area tersebut akan dicadangkan dengan benar ketika Anda juga perlu mempertahankan rasio aspeknya. Kami juga dapat menggunakan placeholder, atau gambar cadangan untuk iklan dan konten dinamis, serta slot tata letak yang telah dialokasikan sebelumnya.
Daripada memuat gambar dengan lambat dengan skrip eksternal, pertimbangkan untuk menggunakan pemuatan lambat asli, atau pemuatan lambat hibrida saat kami memuat skrip eksternal hanya jika pemuatan lambat asli tidak didukung.
Seperti disebutkan di atas, selalu kelompokkan pengecatan ulang font web dan transisi dari semua font fallback ke semua font web sekaligus — pastikan bahwa peralihan itu tidak terlalu mendadak, dengan menyesuaikan tinggi garis dan jarak antara font dengan font-style-matcher .
Untuk mengganti metrik font untuk font fallback guna meniru font web, kita dapat menggunakan deskriptor @font-face untuk mengganti metrik font (demo, diaktifkan di Chrome 87). (Perhatikan bahwa penyesuaian rumit dengan tumpukan font yang rumit.)
Untuk CSS yang lebih baru, kami dapat memastikan bahwa CSS yang sangat penting dalam tata letak digariskan di header setiap template. Lebih jauh dari itu: untuk halaman yang panjang, ketika bilah gulir vertikal ditambahkan, itu menggeser konten utama 16px ke kiri. Untuk menampilkan scrollbar lebih awal, kita dapat menambahkan
overflow-y: scroll
padahtml
untuk menerapkan scrollbar pada first paint. Yang terakhir membantu karena bilah gulir dapat menyebabkan pergeseran tata letak yang tidak sepele karena konten paruh atas mengalir kembali ketika lebar berubah. Seharusnya sebagian besar terjadi pada platform dengan scrollbar non-overlay seperti Windows. Tetapi: breakposition: sticky
karena elemen-elemen itu tidak akan pernah keluar dari wadah.Jika Anda berurusan dengan tajuk yang menjadi tetap atau menempel di bagian atas halaman saat menggulir, sisakan ruang untuk tajuk saat menjadi pine, misalnya dengan elemen placeholder atau
margin-top
pada konten. Pengecualian harus berupa spanduk izin cookie yang seharusnya tidak berdampak pada CLS, tetapi terkadang berdampak: itu tergantung pada penerapannya. Ada beberapa strategi dan takeaways yang menarik di utas Twitter ini.Untuk komponen tab yang mungkin menyertakan berbagai jumlah teks, Anda dapat mencegah pergeseran tata letak dengan tumpukan kisi CSS. Dengan menempatkan konten setiap tab di area kisi yang sama, dan menyembunyikan salah satunya pada satu waktu, kami dapat memastikan bahwa wadah selalu mengambil ketinggian elemen yang lebih besar, sehingga tidak ada perubahan tata letak yang akan terjadi.
Ah, dan tentu saja, pengguliran tak terbatas dan "Muat lebih banyak" dapat menyebabkan pergeseran tata letak juga jika ada konten di bawah daftar (misalnya footer). Untuk meningkatkan CLS, sediakan ruang yang cukup untuk konten yang akan dimuat sebelum pengguna menggulir ke bagian halaman tersebut, hapus footer atau elemen DOM apa pun di bagian bawah halaman yang mungkin terdorong ke bawah oleh pemuatan konten. Selain itu, prefetch data dan gambar untuk konten paruh bawah sehingga pada saat pengguna menggulir sejauh itu, itu sudah ada di sana. Anda dapat menggunakan perpustakaan virtualisasi daftar seperti jendela reaksi untuk mengoptimalkan daftar panjang juga ( terima kasih, Addy Osmani! ).
Untuk memastikan bahwa dampak reflow terkendali, ukur stabilitas tata letak dengan Layout Instability API. Dengannya, Anda dapat menghitung skor Pergeseran Tata Letak Kumulatif ( CLS ) dan memasukkannya sebagai persyaratan dalam pengujian Anda, jadi setiap kali regresi muncul, Anda dapat melacak dan memperbaikinya.
Untuk menghitung skor pergeseran tata letak, browser melihat ukuran area pandang dan pergerakan elemen yang tidak stabil di area pandang antara dua bingkai yang dirender. Idealnya, skor akan mendekati
0
. Ada panduan hebat oleh Milica Mihajlija dan Philip Walton tentang apa itu CLS dan bagaimana mengukurnya. Ini adalah titik awal yang baik untuk mengukur dan mempertahankan kinerja yang dirasakan dan menghindari gangguan, terutama untuk tugas-tugas bisnis yang penting.Kiat cepat : untuk mengetahui apa yang menyebabkan perubahan tata letak di DevTools, Anda dapat menjelajahi perubahan tata letak di bawah "Pengalaman" di Panel Kinerja.
Bonus : jika Anda ingin mengurangi reflows dan repaints, periksa panduan Charis Theodoulou untuk Meminimalkan DOM Reflow/Layout Thrashing dan daftar Paul Irish tentang Apa yang memaksa layout / reflow serta CSSTriggers.com, tabel referensi tentang properti CSS yang memicu layout, paint dan pengomposisian.
Jaringan dan HTTP/2
- Apakah penjepretan OCSP diaktifkan?
Dengan mengaktifkan OCSP stapel di server Anda, Anda dapat mempercepat handshake TLS Anda. Protokol Status Sertifikat Online (OCSP) dibuat sebagai alternatif untuk protokol Daftar Pencabutan Sertifikat (CRL). Kedua protokol tersebut digunakan untuk memeriksa apakah sertifikat SSL telah dicabut.Namun, protokol OCSP tidak mengharuskan browser menghabiskan waktu mengunduh dan kemudian mencari daftar informasi sertifikat, sehingga mengurangi waktu yang diperlukan untuk jabat tangan.
- Sudahkah Anda mengurangi dampak pencabutan sertifikat SSL?
Dalam artikelnya tentang "Biaya Kinerja Sertifikat EV", Simon Hearne memberikan gambaran umum yang bagus tentang sertifikat umum, dan dampak pilihan sertifikat terhadap kinerja secara keseluruhan.Seperti yang ditulis Simon, di dunia HTTPS, ada beberapa jenis tingkat validasi sertifikat yang digunakan untuk mengamankan lalu lintas:
- Validasi Domain (DV) memvalidasi bahwa pemohon sertifikat memiliki domain,
- Validasi Organisasi (OV) memvalidasi bahwa organisasi memiliki domain,
- Extended Validation (EV) memvalidasi bahwa organisasi memiliki domain, dengan validasi yang ketat.
Penting untuk dicatat bahwa semua sertifikat ini sama dalam hal teknologi; mereka hanya berbeda dalam informasi dan properti yang disediakan dalam sertifikat tersebut.
Sertifikat EV mahal dan memakan waktu karena memerlukan manusia untuk meninjau sertifikat dan memastikan validitasnya. Sertifikat DV, di sisi lain, sering diberikan secara gratis — misalnya oleh Let's Encrypt — otoritas sertifikat otomatis terbuka yang terintegrasi dengan baik ke banyak penyedia hosting dan CDN. Faktanya, pada saat penulisan, ini mendukung lebih dari 225 juta situs web (PDF), meskipun hanya menghasilkan 2,69% halaman (dibuka di Firefox).
Jadi apa masalahnya? Masalahnya adalah bahwa sertifikat EV tidak sepenuhnya mendukung stapel OCSP yang disebutkan di atas. Sementara stapel memungkinkan server untuk memeriksa dengan Otoritas Sertifikat jika sertifikat telah dicabut dan kemudian menambahkan ("staple") informasi ini ke sertifikat, tanpa menstaples klien harus melakukan semua pekerjaan, menghasilkan permintaan yang tidak perlu selama negosiasi TLS . Pada koneksi yang buruk, ini mungkin berakhir dengan biaya kinerja yang nyata (1000ms+).
Sertifikat EV bukanlah pilihan yang bagus untuk kinerja web, dan mereka dapat menyebabkan dampak yang jauh lebih besar pada kinerja daripada sertifikat DV. Untuk kinerja web yang optimal, selalu sajikan sertifikat DV yang dijilid OCSP. Mereka juga jauh lebih murah daripada sertifikat EV dan lebih sedikit kerumitan untuk mendapatkannya. Yah, setidaknya sampai CRlite tersedia.
Catatan : Dengan QUIC/HTTP/3 pada kami, perlu dicatat bahwa rantai sertifikat TLS adalah satu-satunya konten berukuran variabel yang mendominasi jumlah byte di QUIC Handshake. Ukurannya bervariasi antara beberapa ratus bye dan lebih dari 10 KB.
Jadi menyimpan sertifikat TLS kecil sangat berarti di QUIC/HTTP/3, karena sertifikat besar akan menyebabkan banyak jabat tangan. Selain itu, kita perlu memastikan bahwa sertifikat dikompresi, karena jika tidak, rantai sertifikat akan terlalu besar untuk dimuat dalam satu penerbangan QUIC.
Anda dapat menemukan lebih banyak detail dan petunjuk untuk masalah dan solusi di:
- Sertifikat EV Membuat Web Lambat dan Tidak Dapat Diandalkan oleh Aaron Peters,
- Dampak pencabutan sertifikat SSL pada kinerja web oleh Matt Hobbs,
- Biaya Kinerja Sertifikat EV oleh Simon Hearne,
- Apakah jabat tangan QUIC memerlukan kompresi agar cepat? oleh Patrick McManus.
- Sudahkah Anda mengadopsi IPv6?
Karena kami kehabisan ruang dengan IPv4 dan jaringan seluler utama mengadopsi IPv6 dengan cepat (AS hampir mencapai ambang adopsi IPv6 50%), sebaiknya perbarui DNS Anda ke IPv6 agar tetap antipeluru di masa mendatang. Pastikan saja bahwa dukungan tumpukan ganda disediakan di seluruh jaringan — ini memungkinkan IPv6 dan IPv4 berjalan secara bersamaan satu sama lain. Lagi pula, IPv6 tidak kompatibel dengan versi sebelumnya. Selain itu, penelitian menunjukkan bahwa IPv6 membuat situs web tersebut 10 hingga 15% lebih cepat karena penemuan tetangga (NDP) dan pengoptimalan rute. - Pastikan semua aset dijalankan melalui HTTP/2 (atau HTTP/3).
Dengan Google mendorong ke arah web HTTPS yang lebih aman selama beberapa tahun terakhir, beralih ke lingkungan HTTP/2 jelas merupakan investasi yang bagus. Faktanya, menurut Web Almanac, 64% dari semua permintaan sudah berjalan melalui HTTP/2.Penting untuk dipahami bahwa HTTP/2 tidak sempurna dan memiliki masalah prioritas, tetapi didukung dengan sangat baik; dan, dalam banyak kasus, Anda lebih baik melakukannya.
Peringatan: HTTP/2 Server Push sedang dihapus dari Chrome, jadi jika implementasi Anda bergantung pada Server Push, Anda mungkin perlu mengunjunginya kembali. Sebagai gantinya, kita mungkin melihat Petunjuk Awal, yang sudah terintegrasi sebagai eksperimen di Fastly.
Jika Anda masih menjalankan HTTP, tugas yang paling memakan waktu adalah bermigrasi ke HTTPS terlebih dahulu, lalu menyesuaikan proses build Anda untuk memenuhi multiplexing dan paralelisasi HTTP/2. Membawa HTTP/2 ke Gov.uk adalah studi kasus yang fantastis untuk melakukan hal itu, menemukan jalan melalui CORS, SRI, dan WPT di sepanjang jalan. Untuk sisa artikel ini, kami berasumsi bahwa Anda beralih ke atau sudah beralih ke HTTP/2.
- Terapkan HTTP/2 dengan benar.
Sekali lagi, melayani aset melalui HTTP/2 dapat mengambil manfaat dari perbaikan sebagian dari cara Anda melayani aset sejauh ini. Anda harus menemukan keseimbangan yang baik antara modul pengemasan dan memuat banyak modul kecil secara paralel. Pada akhirnya, permintaan terbaik tetap tidak ada permintaan, namun, tujuannya adalah untuk menemukan keseimbangan yang baik antara pengiriman aset pertama yang cepat dan caching.Di satu sisi, Anda mungkin ingin menghindari penggabungan aset sama sekali, alih-alih memecah seluruh antarmuka Anda menjadi banyak modul kecil, mengompresinya sebagai bagian dari proses pembuatan dan memuatnya secara paralel. Perubahan dalam satu file tidak memerlukan seluruh style sheet atau JavaScript untuk diunduh ulang. Ini juga meminimalkan waktu penguraian dan menjaga muatan halaman individual tetap rendah.
Di sisi lain, kemasan tetap penting. Dengan menggunakan banyak skrip kecil, kompresi keseluruhan akan terganggu dan biaya pengambilan objek dari cache akan meningkat. Kompresi paket besar akan mendapat manfaat dari penggunaan kembali kamus, sedangkan paket kecil yang terpisah tidak. Ada pekerjaan standar untuk mengatasinya, tetapi itu masih jauh untuk saat ini. Kedua, browser belum dioptimalkan untuk alur kerja seperti itu. Misalnya, Chrome akan memicu komunikasi antar-proses (IPC) linier dengan jumlah sumber daya, sehingga menyertakan ratusan sumber daya akan memiliki biaya runtime browser.
Namun, Anda dapat mencoba memuat CSS secara progresif. Faktanya, CSS in-body tidak lagi memblokir rendering untuk Chrome. Tetapi ada beberapa masalah prioritas sehingga tidak semudah itu, tetapi layak untuk dicoba.
Anda bisa lolos dengan penggabungan koneksi HTTP/2, yang memungkinkan Anda menggunakan domain sharding sambil memanfaatkan HTTP/2, tetapi mencapai ini dalam praktiknya sulit, dan secara umum, itu tidak dianggap sebagai praktik yang baik. Selain itu, HTTP/2 dan Integritas Subsumber daya tidak selalu aktif.
Apa yang harus dilakukan? Nah, jika Anda menggunakan HTTP/2, mengirim sekitar 6–10 paket sepertinya merupakan kompromi yang layak (dan tidak terlalu buruk untuk browser lawas). Eksperimen dan ukur untuk menemukan keseimbangan yang tepat untuk situs web Anda.
- Apakah kami mengirim semua aset melalui satu koneksi HTTP/2?
Salah satu keuntungan utama HTTP/2 adalah memungkinkan kita mengirim aset melalui kabel melalui satu koneksi. Namun, terkadang kami mungkin telah melakukan kesalahan — misalnya memiliki masalah CORS, atau salah mengonfigurasi atributcrossorigin
, sehingga browser terpaksa membuka koneksi baru.Untuk memeriksa apakah semua permintaan menggunakan koneksi HTTP/2 tunggal, atau ada sesuatu yang salah dikonfigurasi, aktifkan kolom "ID Koneksi" di DevTools → Jaringan. Misalnya, di sini, semua permintaan berbagi koneksi yang sama (286) — kecuali manifest.json, yang membuka koneksi terpisah (451).
- Apakah server dan CDN Anda mendukung HTTP/2?
Server dan CDN yang berbeda (masih) mendukung HTTP/2 secara berbeda. Gunakan Perbandingan CDN untuk memeriksa opsi Anda, atau dengan cepat mencari tahu bagaimana kinerja server Anda dan fitur mana yang dapat Anda harapkan untuk didukung.Konsultasikan penelitian luar biasa Pat Meenan tentang prioritas HTTP/2 (video) dan uji dukungan server untuk prioritas HTTP/2. Menurut Pat, direkomendasikan untuk mengaktifkan kontrol kemacetan BBR dan menyetel
tcp_notsent_lowat
ke 16KB agar prioritas HTTP/2 bekerja dengan andal di kernel Linux 4.9 dan yang lebih baru ( terima kasih, Yoav! ). Andy Davies melakukan penelitian serupa untuk prioritas HTTP/2 di seluruh browser, CDN, dan Layanan Cloud Hosting.Saat menggunakannya, periksa kembali apakah kernel Anda mendukung TCP BBR dan aktifkan jika memungkinkan. Saat ini digunakan di Google Cloud Platform, Amazon Cloudfront, Linux (misalnya Ubuntu).
- Apakah kompresi HPACK sedang digunakan?
Jika Anda menggunakan HTTP/2, periksa kembali apakah server Anda menerapkan kompresi HPACK untuk header respons HTTP guna mengurangi overhead yang tidak perlu. Beberapa server HTTP/2 mungkin tidak sepenuhnya mendukung spesifikasi, dengan HPACK sebagai contohnya. H2spec adalah alat yang hebat (jika sangat rinci secara teknis) untuk memeriksanya. Algoritma kompresi HPACK cukup mengesankan, dan berhasil. - Pastikan keamanan di server Anda antipeluru.
Semua implementasi browser HTTP/2 dijalankan di atas TLS, jadi Anda mungkin ingin menghindari peringatan keamanan atau beberapa elemen di halaman Anda tidak berfungsi. Periksa kembali apakah header keamanan Anda disetel dengan benar, hilangkan kerentanan yang diketahui, dan periksa pengaturan HTTPS Anda.Selain itu, pastikan bahwa semua plugin eksternal dan skrip pelacakan dimuat melalui HTTPS, skrip lintas situs tidak dimungkinkan dan header HTTP Strict Transport Security dan header Kebijakan Keamanan Konten disetel dengan benar.
- Apakah server dan CDN Anda mendukung HTTP/3?
Sementara HTTP/2 telah membawa sejumlah peningkatan kinerja yang signifikan ke web, itu juga meninggalkan beberapa area untuk perbaikan — terutama pemblokiran head-of-line di TCP, yang terlihat pada jaringan yang lambat dengan kehilangan paket yang signifikan. HTTP/3 sedang memecahkan masalah ini untuk selamanya (artikel).Untuk mengatasi masalah HTTP/2, IETF, bersama dengan Google, Akamai, dan lainnya, telah mengerjakan protokol baru yang baru-baru ini distandarisasi sebagai HTTP/3.
Robin Marx telah menjelaskan HTTP/3 dengan sangat baik, dan penjelasan berikut didasarkan pada penjelasannya. Pada intinya, HTTP/3 sangat mirip dengan HTTP/2 dalam hal fitur, tetapi cara kerjanya sangat berbeda. HTTP/3 menyediakan sejumlah peningkatan: jabat tangan yang lebih cepat, enkripsi yang lebih baik, aliran independen yang lebih andal, enkripsi dan kontrol aliran yang lebih baik. Perbedaan yang mencolok adalah bahwa HTTP/3 menggunakan QUIC sebagai lapisan transport, dengan paket QUIC yang dienkapsulasi di atas diagram UDP, bukan TCP.
QUIC sepenuhnya mengintegrasikan TLS 1.3 ke dalam protokol, sementara di TCP itu berlapis di atas. Dalam tumpukan TCP yang khas, kami memiliki beberapa waktu bolak-balik overhead karena TCP dan TLS perlu melakukan jabat tangan mereka sendiri yang terpisah, tetapi dengan QUIC keduanya dapat digabungkan dan diselesaikan hanya dalam satu perjalanan pulang pergi . Karena TLS 1.3 memungkinkan kita untuk mengatur kunci enkripsi untuk koneksi konsekuen, dari koneksi kedua dan seterusnya, kita sudah dapat mengirim dan menerima data lapisan aplikasi dalam perjalanan putaran pertama, yang disebut "0-RTT".
Juga, algoritma kompresi header HTTP/2 sepenuhnya ditulis ulang, bersama dengan sistem prioritasnya. Plus, QUIC mendukung migrasi koneksi dari Wi-Fi ke jaringan seluler melalui ID koneksi di header setiap paket QUIC. Sebagian besar implementasi dilakukan di ruang pengguna, bukan ruang kernel (seperti yang dilakukan dengan TCP), jadi kita harus mengharapkan protokol berkembang di masa depan.
Apakah itu semua akan membuat perbedaan besar? Mungkin ya, terutama berdampak pada waktu pemuatan di seluler, tetapi juga pada cara kami menyajikan aset kepada pengguna akhir. Sementara di HTTP/2, beberapa permintaan berbagi koneksi, dalam permintaan HTTP/3 juga berbagi koneksi tetapi streaming secara independen, sehingga paket yang dijatuhkan tidak lagi memengaruhi semua permintaan, hanya satu aliran.
Itu berarti bahwa meskipun dengan satu bundel JavaScript besar, pemrosesan aset akan diperlambat ketika satu aliran dijeda, dampaknya akan kurang signifikan ketika beberapa file mengalir secara paralel (HTTP/3). Jadi kemasan tetap penting .
HTTP/3 masih dalam proses. Chrome, Firefox, dan Safari sudah memiliki implementasi. Beberapa CDN sudah mendukung QUIC dan HTTP/3. Pada akhir tahun 2020, Chrome mulai menerapkan HTTP/3 dan IETF QUIC, dan kenyataannya semua layanan Google (Google Analytics, YouTube, dll.) sudah berjalan melalui HTTP/3. LiteSpeed Web Server mendukung HTTP/3, tetapi Apache, nginx, atau IIS belum mendukungnya, tetapi kemungkinan akan berubah dengan cepat pada tahun 2021.
Intinya : jika Anda memiliki opsi untuk menggunakan HTTP/3 di server dan di CDN Anda, mungkin merupakan ide yang sangat bagus untuk melakukannya. Manfaat utama akan datang dari mengambil beberapa objek secara bersamaan, terutama pada koneksi latensi tinggi. Kami belum tahu pasti karena tidak banyak penelitian yang dilakukan di bidang itu, tetapi hasil pertama sangat menjanjikan.
Jika Anda ingin lebih mendalami spesifikasi dan keunggulan protokol, berikut adalah beberapa titik awal yang baik untuk diperiksa:
- HTTP/3 Dijelaskan, upaya kolaboratif untuk mendokumentasikan HTTP/3 dan protokol QUIC. Tersedia dalam berbagai bahasa, juga sebagai PDF.
- Meningkatkan Kinerja Web Dengan HTTP/3 dengan Daniel Stenberg.
- Panduan Akademik untuk QUIC dengan Robin Marx memperkenalkan konsep dasar protokol QUIC dan HTTP/3, menjelaskan bagaimana HTTP/3 menangani pemblokiran head-of-line dan migrasi koneksi, dan bagaimana HTTP/3 dirancang untuk selalu hijau (terima kasih, Simon !).
- Anda dapat memeriksa apakah server Anda berjalan pada HTTP/3 di HTTP3Check.net.
Pengujian Dan Pemantauan
- Sudahkah Anda mengoptimalkan alur kerja audit Anda?
Ini mungkin tidak terdengar seperti masalah besar, tetapi memiliki pengaturan yang tepat di ujung jari Anda mungkin menghemat sedikit waktu Anda dalam pengujian. Pertimbangkan untuk menggunakan Alur Kerja Alfred Tim Kadlec untuk WebPageTest untuk mengirimkan pengujian ke instance publik WebPageTest. Faktanya, WebPageTest memiliki banyak fitur yang tidak jelas, jadi luangkan waktu untuk mempelajari cara membaca bagan Tampilan Air Terjun WebPageTest dan cara membaca bagan Tampilan Koneksi WebPageTest untuk mendiagnosis dan menyelesaikan masalah kinerja dengan lebih cepat.Anda juga dapat menjalankan WebPageTest dari Google Spreadsheet dan memasukkan skor aksesibilitas, kinerja, dan SEO ke dalam pengaturan Travis Anda dengan Lighthouse CI atau langsung ke Webpack.
Lihatlah AutoWebPerf yang baru dirilis, alat modular yang memungkinkan pengumpulan data kinerja secara otomatis dari berbagai sumber. Misalnya, kami dapat menetapkan pengujian harian pada halaman penting Anda untuk menangkap data lapangan dari CrUX API dan data lab dari laporan Lighthouse dari PageSpeed Insights.
Dan jika Anda perlu men-debug sesuatu dengan cepat tetapi proses pembuatan Anda tampaknya sangat lambat, ingatlah bahwa "penghapusan spasi dan manipulasi simbol menyumbang 95% pengurangan ukuran dalam kode yang diperkecil untuk sebagian besar JavaScript — bukan transformasi kode yang rumit. Anda bisa cukup nonaktifkan kompresi untuk mempercepat build Uglify sebanyak 3 hingga 4 kali."
- Sudahkah Anda menguji di browser proxy dan browser lawas?
Pengujian di Chrome dan Firefox tidak cukup. Lihat cara kerja situs web Anda di browser proxy dan browser lawas. UC Browser dan Opera Mini, misalnya, memiliki pangsa pasar yang signifikan di Asia (hingga 35% di Asia). Ukur kecepatan Internet rata-rata di negara tujuan Anda untuk menghindari kejutan besar di kemudian hari. Uji dengan pembatasan jaringan, dan tiru perangkat DPI tinggi. BrowserStack sangat bagus untuk pengujian pada perangkat nyata jarak jauh , dan melengkapinya dengan setidaknya beberapa perangkat nyata di kantor Anda juga — itu sepadan.
- Sudahkah Anda menguji kinerja halaman 404 Anda?
Biasanya kami tidak berpikir dua kali untuk 404 halaman. Lagi pula, ketika klien meminta halaman yang tidak ada di server, server akan merespons dengan kode status 404 dan halaman 404 terkait. Tidak ada yang banyak untuk itu, bukan?Aspek penting dari 404 respons adalah ukuran isi respons aktual yang dikirim ke browser. Menurut penelitian 404 halaman oleh Matt Hobbs, sebagian besar dari 404 tanggapan berasal dari favicons yang hilang, permintaan unggahan WordPress, permintaan JavaScript yang rusak, file manifes serta file CSS dan font. Setiap kali klien meminta aset yang tidak ada, mereka akan menerima respons 404 — dan seringkali respons itu sangat besar.
Pastikan untuk memeriksa dan mengoptimalkan strategi caching untuk halaman 404 Anda. Tujuan kami adalah menyajikan HTML ke browser hanya saat browser mengharapkan respons HTML, dan mengembalikan muatan kesalahan kecil untuk semua respons lainnya. Menurut Matt, "jika kita menempatkan CDN di depan asal kita, kita memiliki kesempatan untuk men-cache respons halaman 404 pada CDN. Itu berguna karena tanpa itu, memukul halaman 404 dapat digunakan sebagai vektor serangan DoS, dengan memaksa server asal untuk menanggapi setiap permintaan 404 daripada membiarkan CDN merespons dengan versi yang di-cache."
Kesalahan 404 tidak hanya dapat merusak kinerja Anda, tetapi juga dapat membebani lalu lintas, jadi sebaiknya sertakan halaman kesalahan 404 dalam rangkaian pengujian Lighthouse Anda, dan lacak skornya dari waktu ke waktu.
- Sudahkah Anda menguji kinerja permintaan persetujuan GDPR Anda?
Pada masa GDPR dan CCPA, sudah menjadi hal yang umum untuk mengandalkan pihak ketiga untuk memberikan opsi bagi pelanggan UE untuk ikut serta atau tidak ikut pelacakan. Namun, seperti halnya skrip pihak ketiga lainnya, kinerja mereka dapat memiliki dampak yang sangat buruk pada keseluruhan upaya kinerja.Tentu saja, persetujuan yang sebenarnya kemungkinan akan mengubah dampak skrip pada kinerja keseluruhan, jadi, seperti yang dicatat Boris Schapira, kami mungkin ingin mempelajari beberapa profil kinerja web yang berbeda:
- Persetujuan ditolak seluruhnya,
- Persetujuan ditolak sebagian,
- Persetujuan diberikan sepenuhnya.
- Pengguna belum bertindak atas permintaan persetujuan (atau permintaan tersebut diblokir oleh pemblokir konten),
Biasanya permintaan persetujuan cookie seharusnya tidak berdampak pada CLS, tetapi terkadang hal itu terjadi, jadi pertimbangkan untuk menggunakan opsi Osano atau kotak persetujuan cookie gratis dan open source.
Secara umum, ada baiknya melihat kinerja pop-up karena Anda perlu menentukan offset horizontal atau vertikal dari peristiwa mouse dan memposisikan popup dengan benar relatif terhadap jangkar. Noam Rosenthal berbagi pembelajaran tim Wikimedia dalam artikel Studi kasus kinerja web: Pratinjau halaman Wikipedia (juga tersedia sebagai video dan menit).
- Apakah Anda menyimpan CSS diagnostik kinerja?
Meskipun kami dapat menyertakan semua jenis pemeriksaan untuk memastikan bahwa kode non-performant diterapkan, seringkali berguna untuk mendapatkan gambaran singkat tentang beberapa buah yang menggantung rendah yang dapat diselesaikan dengan mudah. Untuk itu, kita dapat menggunakan Performance Diagnostics CSS brilian dari Tim Kadlec (terinspirasi oleh cuplikan Harry Roberts yang menyoroti gambar yang dimuat lambat, gambar tidak berukuran, gambar format lama, dan skrip sinkron.Misalnya, Anda mungkin ingin memastikan bahwa tidak ada gambar di paro atas yang dimuat dengan lambat. Anda dapat menyesuaikan cuplikan untuk kebutuhan Anda, misalnya untuk menyorot font web yang tidak digunakan, atau mendeteksi font ikon. Alat kecil yang hebat untuk memastikan bahwa kesalahan terlihat selama debugging, atau hanya untuk mengaudit proyek saat ini dengan sangat cepat.
/* Performance Diagnostics CSS */ /* via Harry Roberts. https://twitter.com/csswizardry/status/1346477682544951296 */ img[loading=lazy] { outline: 10px solid red; }
- Have you tested the impact on accessibility?
When the browser starts to load a page, it builds a DOM, and if there is an assistive technology like a screen reader running, it also creates an accessibility tree. The screen reader then has to query the accessibility tree to retrieve the information and make it available to the user — sometimes by default, and sometimes on demand. And sometimes it takes time.When talking about fast Time to Interactive, usually we mean an indicator of how soon a user can interact with the page by clicking or tapping on links and buttons. The context is slightly different with screen readers. In that case, fast Time to Interactive means how much time passes by until the screen reader can announce navigation on a given page and a screen reader user can actually hit keyboard to interact.
Leonie Watson has given an eye-opening talk on accessibility performance and specifically the impact slow loading has on screen reader announcement delays. Screen readers are used to fast-paced announcements and quick navigation, and therefore might potentially be even less patient than sighted users.
Large pages and DOM manipulations with JavaScript will cause delays in screen reader announcements. A rather unexplored area that could use some attention and testing as screen readers are available on literally every platform (Jaws, NVDA, Voiceover, Narrator, Orca).
- Is continuous monitoring set up?
Having a private instance of WebPagetest is always beneficial for quick and unlimited tests. However, a continuous monitoring tool — like Sitespeed, Calibre and SpeedCurve — with automatic alerts will give you a more detailed picture of your performance. Set your own user-timing marks to measure and monitor business-specific metrics. Also, consider adding automated performance regression alerts to monitor changes over time.Look into using RUM-solutions to monitor changes in performance over time. For automated unit-test-alike load testing tools, you can use k6 with its scripting API. Also, look into SpeedTracker, Lighthouse and Calibre.
Kemenangan Cepat
This list is quite comprehensive, and completing all of the optimizations might take quite a while. So, if you had just 1 hour to get significant improvements, what would you do? Let's boil it all down to 17 low-hanging fruits . Obviously, before you start and once you finish, measure results, including Largest Contentful Paint and Time To Interactive on a 3G and cable connection.
- Measure the real world experience and set appropriate goals. Aim to be at least 20% faster than your fastest competitor. Stay within Largest Contentful Paint < 2.5s, a First Input Delay < 100ms, Time to Interactive < 5s on slow 3G, for repeat visits, TTI < 2s. Optimize at least for First Contentful Paint and Time To Interactive.
- Optimize images with Squoosh, mozjpeg, guetzli, pingo and SVGOMG, and serve AVIF/WebP with an image CDN.
- Prepare critical CSS for your main templates, and inline them in the
<head>
of each template. For CSS/JS, operate within a critical file size budget of max. 170KB gzipped (0.7MB decompressed). - Trim, optimize, defer and lazy-load scripts. Invest in the config of your bundler to remove redundancies and check lightweight alternatives.
- Always self-host your static assets and always prefer to self-host third-party assets. Limit the impact of third-party scripts. Use facades, load widgets on interaction and beware of anti-flicker snippets.
- Be selective when choosing a framework. For single-page-applications, identify critical pages and serve them statically, or at least prerender them, and use progressive hydration on component-level and import modules on interaction.
- Client-side rendering alone isn't a good choice for performance. Prerender if your pages don't change much, and defer the booting of frameworks if you can. If possible, use streaming server-side rendering.
- Serve legacy code only to legacy browsers with
<script type="module">
and module/nomodule pattern. - Experiment with regrouping your CSS rules and test in-body CSS.
- Add resource hints to speed up delivery with faster
dns-lookup
,preconnect
,prefetch
,preload
andprerender
. - Subset web fonts and load them asynchronously, and utilize
font-display
in CSS for fast first rendering. - Check that HTTP cache headers and security headers are set properly.
- Enable Brotli compression on the server. (If that's not possible, at least make sure that Gzip compression is enabled.)
- Enable TCP BBR congestion as long as your server is running on the Linux kernel version 4.9+.
- Enable OCSP stapling and IPv6 if possible. Always serve an OCSP stapled DV certificate.
- Enable HPACK compression for HTTP/2 and move to HTTP/3 if it's available.
- Cache assets such as fonts, styles, JavaScript and images in a service worker cache.
Download The Checklist (PDF, Apple Pages)
With this checklist in mind, you should be prepared for any kind of front-end performance project. Feel free to download the print-ready PDF of the checklist as well as an editable Apple Pages document to customize the checklist for your needs:
- Download the checklist PDF (PDF, 166 KB)
- Download the checklist in Apple Pages (.pages, 275 KB)
- Download the checklist in MS Word (.docx, 151 KB)
If you need alternatives, you can also check the front-end checklist by Dan Rublic, the "Designer's Web Performance Checklist" by Jon Yablonski and the FrontendChecklist.
Ayo kita pergi!
Some of the optimizations might be beyond the scope of your work or budget or might just be overkill given the legacy code you have to deal with. That's fine! Use this checklist as a general (and hopefully comprehensive) guide, and create your own list of issues that apply to your context. But most importantly, test and measure your own projects to identify issues before optimizing. Happy performance results in 2021, everyone!
A huge thanks to Guy Podjarny, Yoav Weiss, Addy Osmani, Artem Denysov, Denys Mishunov, Ilya Pukhalski, Jeremy Wagner, Colin Bendell, Mark Zeman, Patrick Meenan, Leonardo Losoviz, Andy Davies, Rachel Andrew, Anselm Hannemann, Barry Pollard, Patrick Hamann, Gideon Pyzer, Andy Davies, Maria Prosvernina, Tim Kadlec, Rey Bango, Matthias Ott, Peter Bowyer, Phil Walton, Mariana Peralta, Pepijn Senders, Mark Nottingham, Jean Pierre Vincent, Philipp Tellis, Ryan Townsend, Ingrid Bergman, Mohamed Hussain SH, Jacob Groß, Tim Swalling, Bob Visser, Kev Adamson, Adir Amsalem, Aleksey Kulikov and Rodney Rehm for reviewing this article, as well as our fantastic community which has shared techniques and lessons learned from its work in performance optimization for everybody to use. Anda benar-benar menghancurkan!