Bagaimana Gatsby menghindari Next.js

Penulis artikel, terjemahan yang kami terbitkan hari ini, bekerja sebagai programmer di Antler. Perusahaan ini adalah generator startup global. Ada beberapa hari demo di Antler beberapa kali dalam setahun, menyatukan banyak pembuat startup dan investor dari seluruh dunia. Situasi sekitar COVID-19 memaksa Antler menerjemahkan acara-acaranya ke dalam format online.



Perusahaan ingin memastikan bahwa pengunjung ke acara virtual mereka, tanpa terganggu oleh apa pun, dan tidak terjebak di mana pun, akan melihat hal yang paling penting. Yakni, ide-ide startup yang dihadirkan kepada publik, dinyatakan sebagai konten halaman web. Hari demonstrasi virtual mungkin menarik bagi audiens yang cukup luas. Beberapa anggota audiens ini mungkin berpartisipasi untuk pertama kalinya dalam hal seperti ini. Oleh karena itu, perusahaan harus melakukan segala cara sebaik mungkin dan menyediakan pemuatan halaman dengan kecepatan tinggi yang mewakili para pemula. Mereka memutuskan bahwa ini adalah kasus ketika aplikasi web progresif berkinerja tinggi (PWA, Aplikasi Web Progresif) dapat berguna. Masalah utama adalah menemukan teknologi yang tepat untuk mengembangkan PWA.


Server rendering atau generator situs statis?


Untuk memulai, saya akan memperkenalkan Anda sedikit ke kursus. Semua proyek kami didasarkan pada React dan perpustakaan Material-UI. Sebagai hasilnya, kami awalnya memutuskan untuk tidak pindah dari tumpukan teknologi ini, yang akan memungkinkan kami untuk memastikan kecepatan pengembangan yang tinggi dan membuat proyek baru itu kompatibel dengan apa yang sudah kami miliki. Perbedaan utama antara proyek baru ini dan aplikasi Bereaksi kami yang lain adalah bahwa database untuk mereka dibuat menggunakan aplikasi create-react-app, dan bahwa mereka sepenuhnya ditampilkan pada klien (CSR, Rendering Sisi Klien). Ini, khususnya, mengarah pada fakta bahwa ketika aplikasi awalnya dimuat, pengguna dipaksa untuk mengamati layar putih kosong sementara proyek kode JavaScript memuat, memproses dan mengeksekusi.

Kami membutuhkan tingkat kinerja tanpa kompromi. Oleh karena itu, kami mulai berpikir untuk menggunakan rendering sisi-server (SSR, Server-Side Rendering) atau generator situs statis (SSG, Static Site Generator) sehingga pemuatan awal aplikasi akan secepat mungkin.

Data kami disimpan di Cloud Firestore, dan kami mengaksesnya menggunakan Algolia. Ini memungkinkan kami untuk mengontrol, di tingkat bidang basis data, akses publik ke data dengan kunci API terbatas. Ini juga meningkatkan kinerja kueri. Dari pengalaman, kita tahu bahwa permintaan Algolia lebih cepat dari biasanya, dan Firestore JavaScript SDK yang dikompresi berukuran 86 KB . Dalam kasus Algolia, ini adalah 7,5 Kb .

Selain itu, kami ingin membuat data yang kami berikan kepada pelanggan sesegar mungkin. Ini akan membantu kami untuk dengan cepat memperbaiki data yang salah yang dapat dipublikasikan secara tidak sengaja. Sementara praktik standar SSG menyediakan untuk implementasi permintaan yang relevan untuk data selama perakitan proyek, kami berharap bahwa dalam database kami data akan ditulis cukup sering. Secara khusus, kita berbicara tentang perekaman data yang diprakarsai oleh administrator menggunakan antarmuka yang dapat diaktifkan, dan atas inisiatif pendiri proyek menggunakan portal web. Ini mengarah pada perakitan kompetitif proyek. Selain itu, karena fitur struktural dari basis data kami, perubahan kecil dapat menyebabkan operasi perakitan proyek baru. Ini membuat pipa CI / CD kami sangat tidak efisien. Oleh karena itu, kami membutuhkan permintaan untuk menerima data dari repositori untuk dieksekusi setiap kali pengguna meminta halaman untuk memuat. Sayangnya, ini berarti bahwa solusi kami tidak akan menjadi contoh proyek SSG "bersih".

Awalnya, aplikasi kami dibuat berdasarkan Gatsby, karena kami sudah menggunakan halaman arahan yang dibangun di Gatsby, dan di salah satu dari mereka perpustakaan Material-UI sudah digunakan. Versi pertama proyek membentuk halaman yang, saat data sedang dimuat, menampilkan "kerangka". Pada saat yang sama, cat konten pertama (FCP) berada di wilayah 1 detik.


Mengunduh "kerangka" halaman dengan pemuatan data berikutnya

Solusi ini ternyata menarik, tetapi ada kekurangannya, karena data untuk output halaman tersebut diunduh atas inisiatif klien:

  • Untuk melihat konten halaman, pengguna harus menunggu unduhan halaman ini sendiri dan data yang ditampilkan di dalamnya, diperoleh melalui 4 permintaan ke Algolia.
  • JS- . , React «» . DOM.
  • . , , .

Akibatnya, selama akhir pekan yang panjang, saya memutuskan untuk bereksperimen dengan versi SSR dari proyek yang dibuat menggunakan Next.js. Beruntung bagi saya, dokumentasi untuk Material-UI memiliki contoh proyek untuk Next.js. Karena itu, saya tidak perlu mempelajari semua kerangka ini dari awal. Saya hanya perlu melihat beberapa bagian tutorial dan dokumentasi. Saya mengonversi aplikasi ke proyek yang diberikan di server. Ketika pengguna meminta memuat halaman, server mengeksekusi permintaan untuk data yang diperlukan untuk mengisi halaman. Langkah ini memungkinkan kami untuk menyelesaikan ketiga masalah di atas. Berikut adalah hasil pengujian untuk dua opsi aplikasi.


Hasil meneliti aplikasi menggunakan Google PageSpeed ​​Insights . Di sebelah kiri adalah Gatsby (SSG), di sebelah kanan adalah Next.js (SSR) ( gambar asli )

FCP untuk versi Next.js dari proyek ini sekitar 3 kali lebih tinggi daripada versi yang didasarkan pada Gatsby. Versi Gatsby proyek memiliki Indeks Kecepatan 3,3 detik, sedangkan versi Next.js memiliki 6,2 detik. Waktu ke byte pertama (TTFB, Time To First Byte) adalah 2,56 detik saat menggunakan Next.js, dan 10-20 ms saat menggunakan Gatsby.

Perlu dicatat bahwa versi situs Next.js dikerahkan ke layanan lain (di sini kami menggunakan layanan ZEIT Now dan Firebase Hosting - ini juga dapat memengaruhi peningkatan TTFB). Tetapi, meskipun demikian, jelas bahwa transfer operasi pengunggahan data ke server membuat situs tampak lebih lambat, terlepas dari kenyataan bahwa semua materi halaman dimuat dalam waktu yang hampir bersamaan. Faktanya adalah bahwa dalam proyek Next.js-versi pengguna untuk beberapa waktu hanya melihat halaman putih kosong.


Tangkapan layar menunjukkan memuat dua versi aplikasi. Pengunduhan tidak selesai secara bersamaan. Catatan disinkronkan saat Anda menekan tombol Enter.

Semua ini memberi kami pelajaran penting dari bidang pengembangan web: Anda perlu memberikan umpan balik visual kepada pengguna. Satu studi menemukan bahwa aplikasi yang menggunakan layar kerangka tampaknya memuat lebih cepat.

Hasil ini, apalagi, tidak sesuai dengan suasana hati yang mungkin Anda tangkap jika Anda membaca artikel tentang pengembangan web dalam beberapa tahun terakhir. Yaitu, kita berbicara tentang fakta bahwa tidak ada yang salah dengan menggunakan sumber daya klien, dan bahwa RSK bukanlah solusi komprehensif untuk masalah kinerja.

Kinerja Pembuatan Situs Statis: Membandingkan Gatsby dan Next.js


Sementara dua kerangka kerja yang dipertimbangkan, Gatsby dan Next.js, masing-masing dikenal, karena kemampuan mereka untuk menghasilkan situs statis dan rendering server, dukungan untuk SSG ditingkatkan di Next.js 9.3 , yang menjadikannya pesaing untuk Gatsby.

Pada saat penulisan ini, kemampuan Next.js 'untuk menghasilkan situs statis masih sangat segar. Dia sedikit lebih dari sebulan. Dia masih dilaporkan di halaman pertama proyek. Sekarang tidak ada banyak perbandingan kemampuan SSG dari Gatsby dan Next.js (atau mungkin belum ada perbandingan seperti itu sama sekali). Akibatnya, saya memutuskan untuk melakukan percobaan sendiri.

Saya mengembalikan versi proyek Gatsby ke status ketika data diunduh pada klien, dan membuatnya agar kedua versi aplikasi memiliki set fitur yang persis sama. Yaitu, saya harus menghapus apa yang bertanggung jawab atas plugin Gatsby: fungsi SEO, menghasilkan favicons, manifes PWA. Untuk membandingkan secara eksklusif bundel JavaScript yang dibuat oleh kerangka kerja, saya tidak menyertakan gambar dan konten lain yang diunduh dari sumber eksternal dalam proyek. Kedua versi aplikasi dikerahkan di platform Firebase Hosting. Untuk referensi, dua versi aplikasi dibuat berdasarkan Gatsby 2.20.9 dan Next.js 9.3.4.

Saya menjalankan Lighthouse di komputer saya 6 kali untuk setiap versi. Hasilnya menunjukkan sedikit keuntungan bagi Gatsby.


Nilai rata-rata yang diperoleh setelah 6 Mercusuar diluncurkan untuk setiap kerangka kerja ( gambar asli )

Dalam hal penilaian kinerja secara keseluruhan, versi Next.js hanya sedikit di belakang versi Gatsby. Hal yang sama berlaku untuk FCP dan Indeks Kecepatan. Versi Next Potential First Delay untuk Next.js aplikasi sedikit lebih tinggi daripada versi Gatsby.

Untuk lebih memahami apa yang terjadi, saya membuka tab Network di alat pengembang Chrome. Ternyata, dalam versi proyek Next.js, jumlah fragmen di mana kode JavaScript dibagi adalah 3 lebih banyak daripada dalam versi Gatsby (tidak termasuk file manifes), tetapi kode yang dikompresi adalah 20 KB lebih kecil. Dapatkah permintaan tambahan yang diperlukan untuk mengunduh file-file ini melebihi manfaat dari bundel yang lebih kecil sehingga sangat mengganggu kinerja?


Dalam versi proyek Gatsby, 7 permintaan dieksekusi untuk mengunduh 379 KB data. Dalam versi proyek Next.js - 12 permintaan untuk mengunduh 359 KB data ( gambar asli )

Jika Anda menganalisis kinerja JavaScript, maka alat pengembang mengatakan bahwa versi proyek Next.js memerlukan 300 ms tambahan untuk rendering pertama, dan bahwa versi ini menghabiskan lebih banyak waktu pada tugas Evaluate Script. Dalam alat pengembang, tugas ini bahkan ditandai sebagai "tugas panjang".


Analisis kinerja berbagai opsi proyek menggunakan tab Kinerja alat pengembang Chrome ( gambar asli )

Saya membandingkan kode proyek untuk mengetahui apakah ada perbedaan dalam penerapannya yang dapat mempengaruhi kinerja. Dengan pengecualian menghapus kode yang tidak perlu dan koreksi yang terkait dengan jenis-jenis TypeScript yang hilang, satu-satunya perbedaan adalah penerapan pengguliran halaman yang mulus saat pindah ke bagian-bagiannya masing-masing. Fitur ini sebelumnya diperkenalkan oleh filegatsby-browser.jsdan dipindahkan ke komponen yang diimpor secara dinamis . Akibatnya, kode ini hanya akan berjalan di browser. (Kami menggunakan paket npm gulir halus, dan ketika mengimpornya, ia membutuhkan objekwindow.) Masalah ini mungkin penyebabnya, tapi saya tidak tahu bagaimana cara mengatasinya di Next.js.

Gatsby lebih nyaman dari sudut pandang pengembang


Pada akhirnya, saya memutuskan untuk memilih versi proyek Gatsby. Selain itu, di sini saya tidak memperhitungkan keunggulan kinerja yang sangat kecil yang ditunjukkan Gatsby dibandingkan dengan mekanisme SSG Next.js (saya tidak akan secara serius berpegang pada keunggulan 0,6 detik?). Faktanya adalah bahwa dalam versi Gatsby proyek banyak fitur PWA sudah diimplementasikan, dan saya tidak melihat gunanya menerapkannya lagi dalam versi aplikasi Next.js.

Ketika saya baru saja membuat versi Gatsby proyek yang pertama, saya dapat dengan cepat menambahkan beberapa fitur PWA yang berguna untuk proyek tersebut. Misalnya, untuk menambahkan ke setiap halaman tag meta saya sendiri yang diperlukan untuk SEO, saya hanya perlu membaca manual . Untuk melengkapi proyek dengan manifes PWA, saya hanya perlu menggunakan plugin yang sesuai. Untuk melengkapi proyek dengan favicons yang akan mendukung semua platform yang tersedia (dan dalam hal ini masih ada kekacauan yang mengerikan ), saya bahkan tidak perlu melakukan apa-apa, karena dukungan favicon adalah bagian dari plugin yang bertanggung jawab atas manifes. Sangat nyaman!

Menerapkan fitur yang sama dalam versi aplikasi Next.js akan membutuhkan lebih banyak pekerjaan. Saya harus mencari manual pelatihan, semua jenis "praktik terbaik". Dan fakta bahwa saya akan berhasil, bagaimanapun, tidak akan memberi saya keuntungan apa pun. Bagaimanapun, versi Next.js dari proyek ini tidak berbeda dalam kinerja yang lebih tinggi daripada versi Gatsby-nya. Ini, sebagai tambahan, adalah alasan mengapa saya memutuskan untuk menonaktifkan fitur yang sesuai dari versi Gatsby proyek, membandingkannya dengan versi Next.js. Dokumentasi Next.js lebih ringkas daripada dokumentasi Gatsby (mungkin faktanya adalah Next.js lebih kecil daripada Gatsby) Saya benar-benar menyukai tutorial Next.js. yang di-gamified Tetapi dokumentasi Gatsby yang lebih luas lebih bernilai dengan perkembangan PWA yang sebenarnya, meskipun pada pandangan pertama terlihat sangat besar.


Dokumentasi Gatsby

Benar, saya tidak bisa diam tentang kekuatan Next.js:

  • Berkat tutorial dan dokumentasi singkat dari Next.js, rasanya kerangka ini bisa dipelajari lebih cepat daripada Gatsby.
  • Sistem pemuatan data yang digunakan dalam Next.js didasarkan pada fungsi asinkron dan API Ambil. Akibatnya, ketika mengembangkan Next.js, pengembang tidak memiliki perasaan bahwa ia perlu belajar GraphQL untuk mengambil keuntungan penuh dari kemampuan framework.
  • Next.js TypeScript, Gatsby , ( ). Next.js , , , .

Berkat fakta bahwa Next.js telah meningkatkan dukungan SSG, kerangka kerja ini telah menjadi alat yang ampuh yang memungkinkan, pada tingkat setiap halaman individu, untuk memilih metode bekerja dengannya. Itu bisa SSR, SSG atau CSR.

Bahkan, jika saya dapat membuat aplikasi ini dalam bentuk yang benar-benar statis, maka Next.js akan lebih cocok untuk saya, karena saya bisa menggunakan Algolia JS-API standar dan dapat menyimpan kode untuk memuat data dalam file yang sama dengan dan kode komponen. Karena Algolia tidak memiliki API GraphQL bawaan, dan tidak ada plugin Gatsby untuk Algolia, menerapkan mekanisme seperti itu di Gatsby akan memerlukan penambahan kode ini ke file baru . Dan ini bertentangan dengan cara deklaratif intuitif untuk mendeskripsikan halaman.

Tentang Cara Tambahan untuk Meningkatkan Kinerja Proyek


Setelah kami menyelesaikan masalah dalam memilih kerangka kerja, dapat dicatat bahwa ada cara tambahan untuk meningkatkan kinerja proyek yang tidak terkait dengan kerangka kerja tersebut. Perbaikan-perbaikan ini mungkin membuat peringkat proyek Lighthouse menjadi 100.

  • Di milis Algolia bulan Maret, disarankan untuk menambahkan petunjuk preconnectuntuk lebih meningkatkan kecepatan eksekusi permintaan. (Benar, sayangnya, fragmen kode yang salah diberikan dalam buletin. Ini kode yang benar.)
  • . JS- CSS-, webpack- Gatsby. Gatsby . , , Netlify Amazon S3. , Firebase Hosting, , .
  • Kami menggunakan gambar JPEG dan PNG yang diunggah oleh pembuat startup di aplikasi. Kami tidak mengompres dan mengoptimalkannya. Memperbaiki aspek aplikasi kami ini cukup sulit dan berada di luar cakupan proyek ini. Selain itu, alangkah baiknya jika semua gambar ini dikonversi ke format WebP. Akibatnya, kita harus menyimpan gambar hanya menggunakan satu format grafik yang sangat efisien. Sayangnya, seperti banyak fitur PWA lainnya, tim pengembangan Safari WebKit kecanduan dengan dukungan WebP. Sekarang ini adalah satu-satunya peramban utama yang tidak mendukung format ini.

Ringkasan


Jika kita meringkas secara singkat apa yang kita bicarakan di sini, maka kita dapat mengatakan yang berikut:

  • Output dari versi "kerangka" dari halaman selama pemuatan data oleh klien membuat pengguna merasa operasi situs web lebih cepat daripada ketika pengguna melihat halaman kosong saat server memuat data.
  • Versi gatsby situs hanya sedikit lebih cepat daripada versi Next.js. Namun, sistem plug-in Gatsby dan dokumentasi proyek berkualitas tinggi meningkatkan kegunaan kerangka kerja ini untuk pengembang.

Pembaca yang budiman! Apakah Anda menggunakan generator situs statis atau sistem rendering sisi server untuk mempercepat proyek Anda?


All Articles