Menghancurkan Bangunan Besar Dengan Netlify Dan Selanjutnya.js

Diterbitkan: 2022-03-10
Ringkasan cepat Static Generation sangat bagus untuk performa — hingga aplikasi menjadi terlalu besar dan waktu build melampaui batas. Hari ini, kita akan melihat bagaimana Pembuat Sesuai Permintaan Netlify dapat memperbaikinya. Selain itu, kami memasangkannya dengan Regenerasi Statis Inkremental Next.js untuk pengalaman pengguna dan pengembang terbaik. Dan, tentu saja, tolok ukur hasil tersebut!

Salah satu kesulitan terbesar bekerja dengan situs web yang dibuat secara statis adalah pembangunan yang semakin lambat seiring pertumbuhan aplikasi Anda. Ini adalah masalah yang tak terhindarkan yang dihadapi tumpukan di beberapa titik dan dapat menyerang dari titik yang berbeda tergantung pada jenis produk yang Anda gunakan.

Misalnya, jika aplikasi Anda memiliki beberapa halaman (tampilan, rute) saat membuat artefak penerapan, masing-masing rute tersebut menjadi file. Kemudian, setelah Anda mencapai ribuan, Anda mulai bertanya-tanya kapan Anda dapat menerapkan tanpa perlu merencanakan sebelumnya. Skenario ini biasa terjadi pada platform e-commerce atau blog, yang sudah menjadi bagian besar dari web tetapi tidak semuanya. Rute bukan satu-satunya kemungkinan kemacetan.

Aplikasi yang membutuhkan banyak sumber daya juga pada akhirnya akan mencapai titik balik ini. Banyak generator statis melakukan pengoptimalan aset untuk memastikan pengalaman pengguna terbaik. Tanpa pengoptimalan build (pembangunan inkremental, caching, kami akan segera mendapatkannya) ini pada akhirnya akan menjadi tidak dapat dikelola juga — pikirkan untuk menelusuri semua gambar di situs web: mengubah ukuran, menghapus, dan/atau membuat file baru berulang kali. Dan setelah semua selesai: ingat Jamstack menyajikan aplikasi kami dari tepi Jaringan Pengiriman Konten . Jadi kita masih perlu memindahkan sesuatu dari server tempat mereka dikompilasi ke tepi jaringan.

Arsitektur layanan umum Jamstack
Arsitektur layanan umum Jamstack (Pratinjau besar)

Selain itu, ada juga fakta lain: data sering kali bersifat dinamis, artinya ketika kita membangun aplikasi dan menerapkannya, mungkin diperlukan beberapa detik, beberapa menit, atau bahkan satu jam. Sementara itu, dunia terus berputar, dan jika kita mengambil data dari tempat lain, aplikasi kita pasti akan ketinggalan zaman. Tidak dapat diterima! Bangun lagi untuk memperbarui!

Bangun Sekali, Perbarui Saat Dibutuhkan

Memecahkan Bulky Builds telah menjadi perhatian utama untuk setiap platform, kerangka kerja, atau layanan Jamstack untuk sementara waktu. Banyak solusi berkisar pada build inkremental. Dalam praktiknya, ini berarti bahwa build akan sama besarnya dengan perbedaan yang mereka bawa terhadap penerapan saat ini.

Mendefinisikan algoritma diff bukanlah tugas yang mudah. Agar pengguna akhir benar- benar mendapat manfaat dari peningkatan ini, ada strategi pembatalan cache yang harus dipertimbangkan. Singkat cerita: kami tidak ingin membatalkan cache untuk halaman atau aset yang tidak berubah.

Next.js datang dengan Incremental Static Regeneration ( ISR ). Intinya, ini adalah cara untuk mendeklarasikan untuk setiap rute seberapa sering kita ingin membangunnya kembali. Di bawah tenda, ini menyederhanakan banyak pekerjaan ke sisi server. Karena setiap rute (dinamis atau tidak) akan membangun kembali dirinya sendiri dengan kerangka waktu tertentu, dan itu sangat cocok dengan aksioma Jamstack untuk membatalkan cache pada setiap build. Anggap saja sebagai header max-age tetapi untuk rute di aplikasi Next.js Anda.

Untuk memulai aplikasi Anda, ISR hanya berjarak satu properti konfigurasi. Pada komponen rute Anda (di dalam direktori /pages ) buka metode getStaticProps Anda dan tambahkan kunci validasi revalidate ke objek kembali:

 export async function getStaticProps() { const { limit, count, pokemons } = await fetchPokemonList() return { props: { limit, count, pokemons, }, revalidate: 3600 // seconds } }

Cuplikan di atas akan memastikan halaman saya dibangun kembali setiap jam dan mengambil lebih banyak Pokemon untuk ditampilkan.

Kami masih mendapatkan build massal sesekali (saat mengeluarkan penerapan baru). Tapi ini memungkinkan kami untuk memisahkan konten dari kode, dengan memindahkan konten ke Sistem Manajemen Konten (CMS) kami dapat memperbarui informasi dalam beberapa detik, terlepas dari seberapa besar aplikasi kami. Selamat tinggal webhook untuk memperbarui kesalahan ketik!

Pembangun Sesuai Permintaan

Netlify baru-baru ini meluncurkan On-Demand Builders yang merupakan pendekatan mereka untuk mendukung ISR untuk Next.js, tetapi juga bekerja di seluruh kerangka kerja termasuk Eleventy dan Nuxt. Di sesi sebelumnya, kami menetapkan bahwa ISR adalah langkah besar menuju waktu pembuatan yang lebih pendek dan menangani sebagian besar kasus penggunaan. Namun demikian, peringatan ada di sana:

  1. Pembangunan penuh berdasarkan penerapan berkelanjutan.
    Tahap inkremental hanya terjadi setelah penerapan dan untuk data. Tidak mungkin mengirimkan kode secara bertahap
  2. Bangunan tambahan adalah produk waktu.
    Cache tidak valid berdasarkan waktu. Jadi build yang tidak perlu dapat terjadi, atau pembaruan yang diperlukan mungkin memakan waktu lebih lama tergantung pada periode validasi ulang yang ditetapkan dalam kode.

Infrastruktur penerapan baru Netlify memungkinkan pengembang membuat logika untuk menentukan bagian mana dari aplikasi mereka yang akan dibangun di atas penerapan dan bagian mana yang akan ditangguhkan (dan bagaimana mereka akan ditangguhkan).

  • Kritis
    Tidak ada tindakan yang diperlukan. Semua yang Anda terapkan akan dibangun di atas Push .
  • Tangguhan
    Bagian tertentu dari aplikasi tidak akan dibangun saat diterapkan, itu akan ditangguhkan untuk dibangun sesuai permintaan setiap kali permintaan pertama terjadi, kemudian akan di-cache sebagai sumber daya lain dari jenisnya.

Membuat pembangun Sesuai Permintaan

Pertama-tama, tambahkan paket netlify/functions sebagai devDependency ke proyek Anda:

 yarn add -D @netlify/functions

Setelah selesai, itu sama saja dengan membuat Fungsi Netlify baru. Jika Anda belum menetapkan direktori khusus untuk mereka, netlify/functions/ dan buat file dengan nama apa pun ke builder Anda.

 import type { Handler } from '@netlify/functions' import { builder } from '@netlify/functions' const myHandler: Handler = async (event, context) => { return { statusCode: 200, body: JSON.stringify({ message: 'Built on-demand! ' }), } } export const handler = builder(myHandler)

Seperti yang dapat Anda lihat dari cuplikan di atas, builder sesuai permintaan terpisah dari Fungsi Netlify biasa karena membungkus handlernya di dalam metode builder() . Metode ini menghubungkan fungsi kita ke tugas build. Dan hanya itu yang Anda perlukan agar aplikasi Anda ditangguhkan untuk pembangunan hanya jika diperlukan. Build inkremental kecil dari awal!

Next.js Di Netlify

Untuk membangun aplikasi Next.js di Netlify ada 2 plugin penting yang harus ditambahkan untuk mendapatkan pengalaman yang lebih baik secara umum: Netlify Plugin Cache Next.js dan Essential Next-on-Netlify. Yang pertama men-cache NextJS Anda lebih efisien dan Anda perlu menambahkannya sendiri, sedangkan yang kedua membuat sedikit penyesuaian pada bagaimana arsitektur Next.js dibangun sehingga lebih cocok dengan Netlify dan tersedia secara default untuk setiap proyek baru yang dapat diidentifikasi oleh Netlify. menggunakan Next.js.

Pembuat Sesuai Permintaan Dengan Next.js

Membangun kinerja, menerapkan kinerja, caching, pengalaman pengembang. Ini semua adalah topik yang sangat penting, tetapi banyak — dan membutuhkan waktu untuk menyiapkannya dengan benar. Kemudian kita sampai pada diskusi lama tentang berfokus pada Pengalaman Pengembang daripada Pengalaman Pengguna. Saat itulah hal-hal pergi ke tempat tersembunyi di tumpukan simpanan untuk dilupakan. Tidak juga.

Netlify mendukung Anda. Hanya dalam beberapa langkah, kami dapat memanfaatkan kekuatan penuh Jamstack di aplikasi Next.js kami. Saatnya menyingsingkan lengan baju dan menyatukan semuanya sekarang.

Mendefinisikan Jalur yang Dirender sebelumnya

Jika Anda pernah bekerja dengan pembuatan statis di dalam Next.js sebelumnya, Anda mungkin pernah mendengar tentang metode getStaticPaths . Metode ini ditujukan untuk rute dinamis (templat halaman yang akan merender berbagai halaman). Tanpa terlalu memikirkan seluk-beluk metode ini, penting untuk dicatat bahwa tipe pengembalian adalah objek dengan 2 kunci, seperti dalam Proof-of-Concept kami, ini akan menjadi file rute dinamis [Pokemon]:

 export async function getStaticPaths() { return { paths: [], fallback: 'blocking', } }
  • paths adalah array yang menjalankan semua jalur yang cocok dengan rute ini yang akan dirender sebelumnya
  • fallback memiliki 3 kemungkinan nilai: blocking, true , atau false

Dalam kasus kami, getStaticPaths kami menentukan:

  1. Tidak ada jalur yang akan dirender sebelumnya;
  2. Kapan pun rute ini dipanggil, kami tidak akan menyajikan template fallback, kami akan merender halaman sesuai permintaan dan membuat pengguna menunggu, memblokir aplikasi agar tidak melakukan hal lain.

Saat menggunakan Pembuat Sesuai Permintaan, pastikan strategi penggantian Anda memenuhi tujuan aplikasi Anda, dokumen resmi Next.js: dokumen cadangan sangat berguna.

Sebelum Pembuat Sesuai Permintaan, getStaticPaths kami sedikit berbeda:

 export async function getStaticPaths() { const { pokemons } = await fetchPkmList() return { paths: pokemons.map(({ name }) => ({ params: { pokemon: name } })), fallback: false, } }

Kami mengumpulkan daftar semua halaman pokemon yang ingin kami miliki, memetakan semua objek pokemon menjadi hanya string dengan nama pokemon, dan meneruskan mengembalikan objek { params } yang membawanya ke getStaticProps . fallback kami disetel ke false karena jika rute tidak cocok, kami ingin Next.js menampilkan halaman 404: Not Found .

Anda dapat memeriksa kedua versi yang di-deploy ke Netlify:

  • Dengan Pembuat Sesuai Permintaan: kode, langsung
  • Dihasilkan sepenuhnya statis: kode, langsung

Kode ini juga bersumber terbuka di Github dan Anda dapat dengan mudah menerapkannya sendiri untuk memeriksa waktu pembuatan. Dan dengan antrian ini, kita meluncur ke topik berikutnya.

Membangun Waktu

Seperti disebutkan di atas, demo sebelumnya sebenarnya adalah Proof-of-Concept , tidak ada yang benar-benar baik atau buruk jika kita tidak dapat mengukurnya. Untuk studi kecil kami, saya pergi ke PokeAPI dan memutuskan untuk menangkap semua pokemon.

Untuk tujuan reproduktifitas, saya membatasi permintaan kami (menjadi 1000 ). Ini tidak benar-benar semua dalam API, tetapi memberlakukan jumlah halaman akan sama untuk semua build terlepas dari apakah semuanya diperbarui kapan saja.

 export const fetchPkmList = async () => { const resp = await fetch(`${API}pokemon?limit=${LIMIT}`) const { count, results, }: { count: number results: { name: string url: string }[] } = await resp.json() return { count, pokemons: results, limit: LIMIT, } }

Dan kemudian meluncurkan kedua versi di cabang yang terpisah ke Netlify, berkat penerapan pratinjau, mereka dapat hidup berdampingan pada dasarnya di lingkungan yang sama. Untuk benar-benar mengevaluasi perbedaan antara kedua metode, pendekatan ODB sangat ekstrem, tidak ada halaman yang dirender sebelumnya untuk rute dinamis tersebut. Meskipun tidak direkomendasikan untuk skenario dunia nyata (Anda akan ingin melakukan pra-render rute padat lalu lintas Anda), ini menandai dengan jelas kisaran peningkatan kinerja waktu pembuatan yang dapat kami capai dengan pendekatan ini.

Strategi Jumlah halaman Jumlah Aset Waktu membangun Total waktu penerapan
Sepenuhnya Statis Dihasilkan 1002 1005 2 menit 32 detik 4 menit 15 detik
Pembangun Sesuai Permintaan 2 0 52 detik 52 detik

Halaman di aplikasi PokeDex kecil kami cukup kecil, aset gambar sangat ramping, tetapi keuntungan pada waktu penerapan sangat signifikan. Jika sebuah aplikasi memiliki rute sedang hingga banyak, itu pasti layak untuk mempertimbangkan strategi ODB.

Itu membuat penyebaran Anda lebih cepat dan karenanya lebih andal. Hit kinerja hanya terjadi pada permintaan pertama, dari permintaan berikutnya dan seterusnya, halaman yang dirender akan di-cache tepat di Edge membuat kinerjanya persis sama dengan Fully Static Generated.

Masa Depan: Rendering Persisten Terdistribusi

Pada hari yang sama, On-Demand Builders diumumkan dan diberi akses awal, Netlify juga menerbitkan Request for Comments on Distributed Persistent Rendering (DPR).

DPR adalah langkah selanjutnya untuk On-Demand Builders. Ini memanfaatkan pembangunan yang lebih cepat dengan memanfaatkan langkah-langkah pembangunan asinkron seperti itu dan kemudian menyimpan aset sampai aset tersebut benar-benar diperbarui. Tidak ada lagi full-build untuk situs web 10k halaman. DPR memberdayakan pengembang untuk memiliki kendali penuh dalam membangun dan menerapkan sistem melalui caching yang solid dan menggunakan Pembuat Sesuai Permintaan.

Bayangkan skenario ini: situs web e-niaga memiliki 10 ribu halaman produk, ini berarti akan memakan waktu sekitar 2 jam untuk membangun seluruh aplikasi untuk penerapan. Kita tidak perlu berdebat betapa menyakitkannya ini.

Dengan DPR, kami dapat menetapkan 500 halaman teratas untuk dibuat di setiap penerapan. Halaman lalu lintas terberat kami selalu siap untuk pengguna kami. Tapi, kami adalah toko, yaitu setiap detik penting. Jadi untuk 9500 halaman lainnya, kita dapat menyetel post-build hook untuk memicu pembuatnya — menyebarkan sisa halaman kita secara asinkron dan segera melakukan caching. Tidak ada pengguna yang terluka, situs web kami diperbarui dengan versi secepat mungkin, dan semua hal lain yang tidak ada dalam cache kemudian disimpan.

Kesimpulan

Meskipun banyak poin diskusi dalam artikel ini bersifat konseptual dan implementasinya harus didefinisikan, saya sangat antusias dengan masa depan Jamstack. Kemajuan yang kami lakukan sebagai komunitas berkisar pada pengalaman pengguna akhir.

Apa pendapat Anda tentang Rendering Persisten Terdistribusi? Sudahkah Anda mencoba Pembuat Sesuai Permintaan di aplikasi Anda? Beri tahu saya lebih banyak di komentar atau hubungi saya di Twitter. Saya benar-benar penasaran!

Referensi

  • “Panduan Lengkap Untuk Regenerasi Statis Inkremental (ISR) Dengan Next.js,” Lee Robinson
  • “Pembuatan Lebih Cepat Untuk Situs Besar Di Netlify Dengan Pembuat Sesuai Permintaan,” Asavari Tayal, Blog Netlify
  • “Rendering Persisten Terdistribusi: Pendekatan Jamstack Baru Untuk Pembuatan Lebih Cepat,” Matt Biilmann, Netlify Blog
  • “Rendering Persisten Terdistribusi (DPR),” Cassidy Williams, GitHub