Komposisi, Caching, dan Arsitektur di Next.js Modern

VVercel
컴퓨터/소프트웨어

Transcript

00:00:00(musik ceria) - Oke, halo semuanya.
00:00:06Nama saya Aurora.
00:00:07Saya seorang pengembang web dari Norwegia.
00:00:09Saya bekerja sebagai konsultan di Crane Consulting dan saya juga aktif membangun dengan Next.js app router dalam proyek konsultasi saya saat ini.
00:00:16Hari ini,
00:00:17saya akan mengajarkan pola-pola terkait komposisi,
00:00:19caching,
00:00:20dan arsitektur di Next.js modern yang akan membantu Anda memastikan skalabilitas dan performa.
00:00:24Izinkan saya menyegarkan kembali konsep paling fundamental untuk presentasi ini,
00:00:28yaitu rendering statis dan dinamis.
00:00:30Kita menemui keduanya di Next.js app router.
00:00:33Rendering statis memungkinkan kita membangun situs web yang lebih cepat karena konten yang sudah dirender sebelumnya dapat di-cache dan didistribusikan secara global,
00:00:40memastikan pengguna dapat mengaksesnya lebih cepat.
00:00:42Contohnya, situs web Next.js Conf.
00:00:46Rendering statis mengurangi beban server karena konten tidak perlu dibuat untuk setiap permintaan pengguna.
00:00:51Konten yang sudah dirender sebelumnya juga lebih mudah diindeks oleh perayap mesin pencari karena konten sudah tersedia saat halaman dimuat.
00:00:58Rendering dinamis,
00:00:59di sisi lain,
00:01:00memungkinkan aplikasi kita menampilkan data real-time atau yang sering diperbarui.
00:01:05Ini juga memungkinkan kita menyajikan konten yang dipersonalisasi,
00:01:08seperti dasbor dan profil pengguna.
00:01:09Contohnya, dasbor Vercel.
00:01:12Dengan rendering dinamis,
00:01:13kita bisa mengakses informasi yang hanya bisa diketahui pada saat permintaan.
00:01:16Dalam kasus ini,
00:01:17pengguna mana yang mengakses dasbor mereka,
00:01:19yaitu saya.
00:01:20Ada API tertentu yang dapat menyebabkan halaman dirender secara dinamis.
00:01:25Penggunaan prop `params` dan `searchParams` yang diteruskan ke halaman atau hook yang setara akan menyebabkan rendering dinamis.
00:01:32Namun,
00:01:32dengan `params`,
00:01:33kita dapat menentukan serangkaian halaman yang sudah dirender sebelumnya menggunakan `static params` generik,
00:01:37dan kita juga dapat melakukan cache halaman saat dibuat oleh pengguna.
00:01:40Selain itu,
00:01:41membaca cookie dan header permintaan yang masuk akan membuat halaman memilih rendering dinamis.
00:01:46Namun,
00:01:47tidak seperti `params`,
00:01:48mencoba melakukan cache atau pra-render apa pun menggunakan header atau cookie akan menimbulkan kesalahan saat build karena informasi tersebut tidak dapat diketahui sebelumnya.
00:01:56Terakhir,
00:01:56menggunakan `fetch` dengan konfigurasi cache data `no-store` juga akan memaksa rendering dinamis.
00:02:00Jadi ini adalah beberapa,
00:02:02ada beberapa API lagi yang dapat menyebabkan rendering dinamis,
00:02:04tetapi ini adalah yang paling sering kita temui.
00:02:06Pada versi Next sebelumnya,
00:02:08sebuah halaman akan dirender baik sebagai statis penuh atau dinamis penuh.
00:02:13Satu API dinamis di sebuah halaman akan membuat seluruh halaman memilih rendering dinamis.
00:02:17Contohnya,
00:02:18melakukan pemeriksaan otentikasi sederhana untuk nilai cookie.
00:02:20Dengan memanfaatkan komponen server React dengan `Suspense`,
00:02:23kita dapat mengalirkan konten dinamis seperti spanduk selamat datang yang dipersonalisasi atau rekomendasi saat siap,
00:02:29dan hanya menyediakan fallback dengan `Suspense` sambil menampilkan konten statis seperti buletin.
00:02:34Namun,
00:02:34setelah kita menambahkan beberapa komponen asinkron pada halaman dinamis seperti produk unggulan,
00:02:39komponen tersebut juga akan berjalan pada waktu permintaan meskipun tidak bergantung pada API dinamis.
00:02:45Jadi,
00:02:45untuk menghindari pemblokiran pemuatan halaman awal,
00:02:48kita akan menangguhkan dan mengalirkan komponen-komponen tersebut juga,
00:02:51melakukan pekerjaan ekstra,
00:02:52membuat kerangka,
00:02:53dan mengkhawatirkan hal-hal seperti pergeseran tata letak.
00:02:56Namun,
00:02:56halaman seringkali merupakan campuran konten statis dan dinamis.
00:03:01Contohnya,
00:03:01aplikasi e-commerce yang bergantung pada informasi pengguna tetapi masih berisi sebagian besar data statis.
00:03:07Dipaksa memilih di antara keduanya,
00:03:09antara statis atau dinamis,
00:03:11menyebabkan banyak pemrosesan berlebihan di server pada konten yang tidak pernah atau sangat jarang berubah dan tidak optimal untuk performa.
00:03:19Jadi untuk mengatasi masalah ini,
00:03:21pada Next.js Conf tahun lalu,
00:03:23direktif `use cache` diumumkan.
00:03:26Dan tahun ini,
00:03:27seperti yang kita lihat di keynote,
00:03:29itu tersedia di Next.js 16.
00:03:30Jadi dengan `use cache`,
00:03:32halaman tidak lagi dipaksa menjadi rendering statis atau dinamis.
00:03:36Keduanya bisa.
00:03:37Dan Next.js tidak perlu lagi menebak jenis halaman berdasarkan apakah halaman tersebut mengakses hal-hal seperti `params`.
00:03:43Semuanya dinamis secara default dan `use cache` memungkinkan kita secara eksplisit memilih untuk melakukan caching.
00:03:47`Use cache` memungkinkan caching yang dapat disusun.
00:03:51Kita bisa menandai halaman,
00:03:53komponen React,
00:03:53atau fungsi sebagai dapat di-cache.
00:03:55Di sini,
00:03:56kita sebenarnya bisa melakukan cache komponen produk unggulan karena tidak memerlukan permintaan dan pemrosesan serta tidak menggunakan API dinamis.
00:04:03Dan segmen cache ini dapat dirender sebelumnya dan disertakan sebagai bagian dari shell statis dengan pra-rendering parsial,
00:04:10artinya produk unggulan sekarang tersedia saat halaman dimuat dan tidak perlu di-stream.
00:04:14Jadi sekarang setelah kita memiliki pengetahuan latar belakang yang penting ini,
00:04:18mari kita lakukan demo.
00:04:19Peningkatan pada basis kode dengan masalah umum yang sering ditemui di aplikasi Next.js.
00:04:24Ini termasuk `prop drilling` yang dalam,
00:04:25membuatnya sulit untuk memelihara dan memfaktorkan ulang fitur,
00:04:28JavaScript sisi klien yang berlebihan dan komponen besar dengan banyak tanggung jawab,
00:04:31serta kurangnya rendering statis,
00:04:33yang menyebabkan biaya server tambahan dan performa yang menurun.
00:04:36Baiklah, mari kita mulai.
00:04:37Dan beri saya waktu sebentar di sini.
00:04:50Oke, bagus.
00:04:54Jadi ini adalah aplikasi yang sangat sederhana.
00:04:56Ini terinspirasi dari platform e-commerce.
00:04:59Dan izinkan saya melakukan demo awal di sini.
00:05:01Jadi saya bisa memuat halaman ini.
00:05:03Saya punya beberapa konten seperti produk unggulan ini.
00:05:06Saya punya kategori unggulan, data produk yang berbeda.
00:05:09Ada juga halaman Jelajahi Semua di sini tempat saya bisa melihat semua produk di platform dan berpindah halaman di antaranya.
00:05:20Lalu kita punya halaman Tentang di sini, yang hanya statis.
00:05:24Saya juga bisa masuk sebagai pengguna.
00:05:27Dan itu akan membuat saya masuk ke akun pengguna saya.
00:05:30Dan juga mendapatkan konten yang dipersonalisasi di dasbor saya di sini.
00:05:33Seperti misalnya,
00:05:34produk yang direkomendasikan atau diskon yang dipersonalisasi ini.
00:05:38Jadi perhatikan di sini, ada campuran yang cukup bagus.
00:05:42Oh, satu halaman lagi yang lupa saya tunjukkan.
00:05:45Halaman produk, yang paling penting.
00:05:47Juga di sini,
00:05:48kita bisa melihat informasi produk dan kemudian menyimpannya jika kita suka untuk pengguna kita.
00:05:52Jadi perhatikan bahwa ada campuran yang cukup bagus antara konten statis dan dinamis di aplikasi ini karena semua fitur yang bergantung pada pengguna.
00:05:59Mari kita lihat juga kodenya, yang ada di sini.
00:06:05Jadi saya menggunakan `app router` di sini,
00:06:07tentu saja,
00:06:07di Next.js 16.
00:06:08Saya punya semua halaman yang berbeda,
00:06:10seperti halaman Tentang,
00:06:11halaman Semua,
00:06:12halaman produk kita.
00:06:13Saya juga punya-- saya menggunakan `feature slicing` di sini untuk menjaga folder aplikasi saya tetap rapi.
00:06:17Saya punya komponen dan kueri yang berbeda yang berkomunikasi dengan database saya menggunakan Prisma.
00:06:23Jadi ya, dan saya sengaja memperlambat semua ini.
00:06:25Itulah mengapa kita memiliki tahap pemuatan yang sangat panjang ini,
00:06:28agar kita bisa lebih mudah melihat apa yang terjadi.
00:06:31Jadi masalah umum yang ingin kami kerjakan di sini yang sebenarnya kami miliki di aplikasi ini adalah `prop drilling`,
00:06:37membuatnya sulit untuk memelihara fitur refactor,
00:06:40akses JavaScript sisi klien,
00:06:41dan kurangnya rendering statis yang menyebabkan biaya server tambahan dan performa terintegrasi.
00:06:47Jadi tujuan demo ini pada dasarnya hanya untuk meningkatkan aplikasi ini dengan beberapa pola cerdas terkait komposisi,
00:06:53caching,
00:06:53dan arsitektur untuk memperbaiki fitur-fitur umum tersebut dan membuatnya lebih cepat,
00:06:58lebih skalabel,
00:06:59dan lebih mudah dipelihara.
00:07:01Jadi mari kita mulai dengan itu.
00:07:02Masalah pertama yang ingin kita perbaiki sebenarnya terkait dengan `prop drilling`.
00:07:05Dan itu ada di sini di halaman.
00:07:10Perhatikan di sini,
00:07:11saya punya variabel `loggedIn` ini di bagian atas.
00:07:15Dan Anda bisa lihat saya meneruskannya ke beberapa komponen.
00:07:17Sebenarnya sudah diteruskan beberapa tingkat ke dalam spanduk pribadi ini.
00:07:20Jadi ini akan menyulitkan untuk menggunakan kembali sesuatu di sini karena kita selalu memiliki dependensi `loggedIn` ini untuk spanduk selamat datang kita.
00:07:28Jadi dengan komponen server,
00:07:29praktik terbaik adalah benar-benar mendorong pengambilan data ke dalam komponen yang menggunakannya dan menyelesaikan `promise` lebih dalam ke dalam pohon.
00:07:37Dan agar ini terotentikasi,
00:07:39selama ini menggunakan `fetch` atau sesuatu seperti `React cache`,
00:07:42kita bisa menduplikasi beberapa panggilan ini,
00:07:44dan kita bisa menggunakannya kembali di mana saja yang kita suka di dalam komponen kita.
00:07:48Jadi itu akan sangat baik untuk digunakan kembali.
00:07:51Jadi sekarang kita bisa memindahkan ini ke bagian yang dipersonalisasi di sini.
00:07:54Dan kita tidak-- tidak akan membutuhkan `prop` ini lagi.
00:07:57Dan cukup letakkan langsung-- aduh-- di sini.
00:08:01Dan kita tidak perlu meneruskan ini lagi.
00:08:04Dan karena kita sekarang memindahkan panggilan asinkron ini ke bagian yang dipersonalisasi,
00:08:07kita tidak lagi memblokir halaman.
00:08:09Kita bisa melanjutkan dan menangguhkan ini hanya dengan `Suspense` sederhana di sini.
00:08:13Dan kita tidak akan membutuhkan `fallback` ini.
00:08:16Untuk spanduk selamat datang,
00:08:19saya kira kita akan melakukan hal yang sama.
00:08:22Tapi mencoba menggunakan-- mendapatkan variabel atau nilai `loggedIn` di sini,
00:08:26itu tidak berfungsi,
00:08:27kan?
00:08:27Karena ini adalah komponen klien.
00:08:29Jadi kita perlu menyelesaikannya dengan cara yang berbeda.
00:08:30Dan kita akan menggunakan pola yang cukup cerdas di sini untuk menyelesaikannya.
00:08:33Kita sebenarnya akan masuk ke `layout` dan membungkus semuanya di sini dengan `auth provider`.
00:08:39Jadi saya akan meletakkan ini di sekitar seluruh aplikasi saya di sini dan mendapatkan variabel `loggedIn` ini di sini.
00:08:45Dan saya jelas tidak ingin memblokir seluruh `root layout` saya.
00:08:48Mari kita lanjutkan dan hapus `await` di sini.
00:08:50Dan cukup teruskan ini sebagai `promise` ke `auth provider` ini.
00:08:55Dan ini bisa saja berisi `promise` itu.
00:08:57Itu bisa saja 'bersantai' di sana sampai kita siap membacanya.
00:09:01Jadi sekarang kita sudah menyiapkan ini.
00:09:03Itu berarti kita sebenarnya bisa melanjutkan dan kita akan menyingkirkan `prop` ini,
00:09:08pertama-tama.
00:09:09Dan kita akan menyingkirkan `prop drilling` yang ini ke `personal banner`.
00:09:12Dan kita akan menyingkirkan `prop drilling` juga di sini atau tanda tangan.
00:09:16Dan sekarang kita bisa menggunakan `auth provider` ini untuk mengambil nilai `loggedIn` ini secara lokal di dalam `personal banner` dengan `useAuth` dengan `provider` yang baru saja kita buat.
00:09:26Dan membacanya dengan `use`.
00:09:28Jadi ini sebenarnya akan berfungsi seperti dalam cara di mana kita perlu menangguhkan ini saat sedang menyelesaikan.
00:09:33Jadi sekarang saya baru saja menempatkan pengambilan data kecil itu di dalam `personal banner`.
00:09:37Dan saya tidak harus meneruskan `prop` itu ke mana-mana.
00:09:40Dan saat ini sedang menyelesaikan,
00:09:41mari kita lanjutkan dan menangguhkan yang ini juga dengan `fallback`.
00:09:44Dan mari kita buat spanduk umum di sini untuk menghindari pergeseran kumulatif yang aneh.
00:09:51Dan akhirnya, singkirkan juga yang ini.
00:09:53Jadi sekarang spanduk selamat datang ini dapat disusun.
00:09:58Ini dapat digunakan kembali.
00:09:59Kita tidak punya `prop` atau dependensi aneh di halaman beranda.
00:10:02Dan karena kita bisa menggunakannya kembali dengan sangat mudah,
00:10:06mari kita lanjutkan dan tambahkan juga ke halaman browser ini di sini,
00:10:10yang akan ada di sini.
00:10:11Dan saya bisa langsung menggunakannya di sini tanpa dependensi apa pun.
00:10:15Jadi melalui pola-pola ini,
00:10:17kita dapat mempertahankan arsitektur komponen yang baik dengan memanfaatkan `React cache`,
00:10:24`React use`,
00:10:25dan membuat komponen kita lebih dapat digunakan dan disusun.
00:10:30Baiklah.
00:10:31Mari kita atasi tantangan umum berikutnya,
00:10:34yaitu JavaScript sisi klien yang berlebihan dan komponen besar dengan banyak tanggung jawab.
00:10:40Sebenarnya, itu juga ada di halaman Semua di sini.
00:10:43Dan lagi, kita harus mengerjakan spanduk selamat datang ini.
00:10:46Saat ini ini adalah komponen klien.
00:10:48Dan alasan mengapa ini adalah komponen klien adalah karena saya memiliki `state dismissed` yang sangat sederhana di sini.
00:10:53Saya bisa mengklik ini.
00:10:54Ini adalah interaksi UI yang bagus.
00:10:56Tidak masalah.
00:10:57Namun,
00:10:57yang tidak begitu baik adalah karena itu,
00:11:00saya mengubah seluruh komponen ini menjadi komponen sisi klien atau komponen klien.
00:11:04Dan saya bahkan menggunakan `swr` untuk mengambil data sisi klien.
00:11:07Saya sekarang punya lapisan API ini di sini.
00:11:08Saya tidak punya `type safety` lagi di data saya.
00:11:11Ya, ini tidak perlu.
00:11:12Dan kita juga melanggar pemisahan kekhawatiran di sini karena kita melibatkan logika UI dengan data.
00:11:18Jadi mari kita lanjutkan dan gunakan pola cerdas lain untuk memperbaikinya.
00:11:21Ini disebut pola donat.
00:11:23Pada dasarnya,
00:11:23yang akan saya lakukan adalah mengekstrak ini ke dalam `wrapper` sisi klien.
00:11:27Jadi mari kita buat komponen baru di sini.
00:11:29Dan mari kita sebut `banner container`.
00:11:32Dan ini akan berisi logika interaktif kita dengan direktif `use client`.
00:11:37Kita bisa membuat tanda tangan.
00:11:38Kita bisa menempelkan semua yang baru saja kita miliki sebelumnya.
00:11:42Dan alih-alih menggunakan spanduk-spanduk ini,
00:11:45saya hanya akan menyisipkan `prop` di sini,
00:11:47yaitu `children`.
00:11:48Jadi inilah mengapa disebut pola donat.
00:11:50Kita hanya membuat logika UI `wrapper` ini di sekitar konten yang dirender server,
00:11:54atau bisa juga konten yang dirender server.
00:11:56Dan kemudian karena kita tidak lagi memiliki dependensi sisi klien ini,
00:11:59kita bisa melanjutkan dan menghapus `use client`.
00:12:01Kita bisa menggunakan fungsi asinkron `isAuth` kita di sini sebagai gantinya.
00:12:06Kita bisa mengubah ini menjadi komponen server asinkron.
00:12:09Kita bahkan bisa mengganti pengambilan data sisi klien dengan pengambilan data sisi server.
00:12:11Jadi izinkan saya langsung mengambil data diskon di sini.
00:12:16Data diskon.
00:12:18Dan cukup manfaatkan model mental reguler kita seperti sebelumnya dengan `type safety`.
00:12:24Dan itu berarti saya juga bisa menghapus lapisan API ini yang tidak ingin saya gunakan.
00:12:29Terakhir,
00:12:29untuk `isLoading`,
00:12:30kita bisa mengekspor spanduk selamat datang baru di sini dengan `banner container` pola donat kita yang berisi konten yang dirender server.
00:12:38Dan itu berarti kita tidak membutuhkan `isLoading` ini lagi.
00:12:40Jadi pada dasarnya kita memfaktorkan ulang seluruh hal ini menjadi komponen server dan mengekstrak titik logika UI.
00:12:46Tapi apa itu?
00:12:48Sepertinya saya punya kesalahan lain.
00:12:51Jadi ini sebenarnya karena Motion.
00:12:53Gunakan Motion.
00:12:54Ini adalah pustaka animasi yang sangat bagus,
00:12:57tetapi membutuhkan direktif `useClient`.
00:12:59Dan lagi,
00:12:59kita tidak perlu membuat ini `useClient` hanya untuk animasi.
00:13:03Kita bisa membuat,
00:13:04lagi,
00:13:05`wrapper` pola donat dan hanya mengekstrak `wrapper` untuk animasi ini.
00:13:10Dan itu berarti kita tidak perlu mengubah apa pun di sini menjadi sisi klien.
00:13:14Dan saya mungkin melewatkan sesuatu di sini.
00:13:17Ya.
00:13:18Itu dia.
00:13:21Jadi sekarang semuanya di sini telah dikonversi ke server.
00:13:23Kita punya interaksi yang sama.
00:13:24Kita masih punya logika interaktif kita di sini,
00:13:27tapi sekarang kita punya satu cara ini untuk mengambil data.
00:13:29Dan kita punya lebih sedikit JS sisi klien.
00:13:31Sebenarnya,
00:13:32saya sendiri menggunakan pola donat ini untuk `UI boundary helper` ini,
00:13:39yang terlihat seperti ini.
00:13:42Anda lihat itu?
00:13:43Jadi ini semacam menunjukkan,
00:13:44lagi,
00:13:45apa yang saya maksud,
00:13:45kan?
00:13:45Dengan pola donat,
00:13:46kita punya komponen klien ini di sekitar komponen server.
00:13:49Saya juga menandai banyak komponen saya yang lain dengan `UI helper` ini di sini.
00:13:53Juga di sini, saya punya lebih banyak komponen server.
00:13:56Mari kita lanjutkan dan tingkatkan itu juga,
00:13:59karena kita sudah cukup mahir sekarang.
00:14:01Mereka ada di `footer`.
00:14:04Kategori-kategori ini-- maksud saya,
00:14:05saya punya komponen bagus ini yang mengambil datanya sendiri.
00:14:08Dan saya hanya ingin menambahkan fitur `showMore` ini,
00:14:11jaga-jaga jika terlalu panjang.
00:14:14Dan dengan pola donat,
00:14:15saya bisa membungkus komponen `showMore` di sini.
00:14:20Dan ini akan berisi logika UI saya.
00:14:23Dan terlihat seperti ini, kan?
00:14:27Cukup keren.
00:14:28Dan ini sekarang berisi logika klien,
00:14:30memungkinkan kita menggunakan `state`.
00:14:33Kita menggunakan `children count` dan `to array` untuk memotong ini.
00:14:36Dan yang keren di sini adalah kedua ini sekarang sepenuhnya komponen yang dapat disusun,
00:14:40dapat digunakan kembali yang bekerja bersama seperti ini.
00:14:42Jadi ini benar-benar keindahan dari pola-pola yang kita pelajari di sini.
00:14:45Anda bisa menggunakan ini untuk apa saja.
00:14:50Saya juga menggunakannya untuk modal ini di sini.
00:14:52Ya,
00:14:52ingat saja ini lain kali Anda mempertimbangkan untuk menambahkan logika klien apa pun ke komponen server Anda.
00:14:59Oke, kita tahu pola donat.
00:15:01Kita tahu cara memanfaatkannya untuk membuat komponen yang dapat disusun ini dan menghindari `plans.js`,
00:15:07jadi kita bisa melanjutkan ke masalah terakhir.
00:15:10Izinkan saya menutup ini lagi.
00:15:13Jadi itu akan terkait dengan kurangnya strategi rendering statis,
00:15:18kan?
00:15:18Melihat output build saya,
00:15:20saya sebenarnya memiliki setiap halaman sebagai halaman dinamis di sini.
00:15:24Jadi itu berarti setiap kali saya memuat sesuatu di sini,
00:15:27ini akan berjalan untuk setiap pengguna.
00:15:29Maaf.
00:15:30Setiap pengguna yang membuka ini akan mendapatkan `loading state` ini.
00:15:33Ini akan membuang-buang biaya server,
00:15:35membuat performa lebih buruk.
00:15:37Dan itu berarti juga bahwa sesuatu di dalam halaman saya menyebabkan rendering dinamis atau memaksa rendering dinamis untuk semua halaman saya.
00:15:45Sebenarnya, itu ada di dalam `root layout` saya.
00:15:49Saya tidak tahu apakah Anda mengalaminya.
00:15:51Itu ada di sini.
00:15:53Di `header` saya, saya punya profil pengguna ini.
00:15:57Dan ini,
00:15:57tentu saja,
00:15:58menggunakan `cookie` untuk mendapatkan pengguna saat ini,
00:16:00dan itu berarti semua hal lainnya juga dirender secara dinamis.
00:16:02Karena lagi, halaman bisa dinamis atau statis, kan?
00:16:06Ini adalah masalah yang cukup umum dan sesuatu yang telah diselesaikan sebelumnya di versi Next sebelumnya,
00:16:11jadi mari kita lihat apa yang bisa kita lakukan.
00:16:13Satu hal yang bisa kita lakukan adalah membuat `route group` dan membagi aplikasi kita menjadi bagian statis dan dinamis yang akan memungkinkan saya mengekstrak halaman Tentang saya.
00:16:23Saya bisa merender ini secara statis.
00:16:25Tidak masalah untuk beberapa aplikasi,
00:16:27tetapi dalam kasus saya,
00:16:28halaman penting adalah halaman produk,
00:16:30dan ini masih dinamis,
00:16:31jadi tidak terlalu membantu.
00:16:33Bagaimana dengan strategi ini?
00:16:35Jadi di sini saya membuat `request context param` ini yang mengkodekan `state` tertentu ke dalam URL saya,
00:16:40dan kemudian saya bisa menggunakan `generate static params` untuk menghasilkan semua varian halaman saya yang berbeda.
00:16:46Itu sebenarnya,
00:16:47dikombinasikan dengan pengambilan data pengguna sisi klien,
00:16:50akan memungkinkan saya untuk mendapatkan ini di-cache di halaman produk saya.
00:16:54Jelas pola yang layak.
00:16:55Ini direkomendasikan oleh Vercel Flags SDK yang disebut pola `precompute`,
00:17:00saya kira.
00:17:00Tapi ini sangat kompleks,
00:17:01dan saya punya banyak cara untuk mengambil data.
00:17:04Dan sebenarnya,
00:17:04saya tidak ingin menulis ulang seluruh aplikasi saya menjadi seperti ini.
00:17:07Jadi bagaimana jika kita tidak perlu melakukan semua solusi itu?
00:17:10Bagaimana jika ada cara yang lebih sederhana?
00:17:12Nah, ada.
00:17:14Mari kita kembali ke aplikasi kita lagi.
00:17:17Jadi kita sebenarnya bisa pergi ke `next config` dan cukup mengaktifkan `cache components`.
00:17:23Oh, bagus.
00:17:25Oke,
00:17:25dan apa yang dilakukan ini,
00:17:27seperti yang Anda tahu dari `keynote`,
00:17:29sebenarnya akan membuat semua panggilan asinkron kita menjadi `request time` atau dinamis.
00:17:34Dan itu juga akan memberi kita kesalahan setiap kali kita memiliki panggilan asinkron yang tidak ditangguhkan,
00:17:40dan itu akan memberi kita direktif `use cache` ini yang dapat kita gunakan untuk melakukan cache secara granular baik halaman,
00:17:47fungsi,
00:17:47atau komponen.
00:17:48Jadi ya, mari kita lanjutkan dan manfaatkan ini.
00:17:51Kita bisa mulai dengan halaman beranda di sini.
00:17:55Mari kita lihat.
00:17:56Jadi lagi,
00:17:56saya punya campuran konten statis dan dinamis ini.
00:17:59Saya punya spanduk selamat datang untuk saya,
00:18:01sesuatu untuk Anda juga untuk saya.
00:18:03Mari kita lihat itu dengan `UI helper` ini lagi.
00:18:06Jadi misalnya,
00:18:07spanduk dirender secara dinamis dengan ini di sini.
00:18:10Sedangkan saya menandai ini sebagai `hybrid rendering` karena `hero`,
00:18:15itu mengambil hal asinkron ini dan berjalan cukup lambat.
00:18:18Tapi itu tidak bergantung pada jenis data pengguna atau API dinamis apa pun.
00:18:21Jadi itu berarti bahwa semua yang dirender secara hibrida di sini sebenarnya dapat digunakan kembali di seluruh permintaan dan di seluruh pengguna.
00:18:27Dan kita bisa menggunakan direktif `use cache` pada itu.
00:18:30Jadi mari kita tambahkan direktif `use cache` di sini dan tandai ini sebagai di-cache.
00:18:35Dan itu akan memungkinkan saya untuk-- setiap kali saya memuat ulang halaman ini-- saya tidak menyimpan ini.
00:18:43Itu dia.
00:18:44Ini tidak akan memuat ulang bagian ini karena sudah di-cache.
00:18:47Sekarang statis, kan?
00:18:49Dan ada juga API terkait lainnya seperti `cache tag` untuk memungkinkan saya mengetik ini atau memvalidasi entri cache tertentu secara granular atau menentukan periode pengungkapan saya.
00:19:01Tapi untuk demo ini, mari kita fokus pada direktif biasa.
00:19:05Sekarang setelah saya memiliki direktif `use cache` ini,
00:19:07saya sebenarnya bisa menghapus `suspense boundary` saya di sekitar `hero` ini.
00:19:10Dan itu berarti-- nah,
00:19:12apa yang akan dilakukan ini adalah `partial prerendering` sebenarnya bisa melanjutkan dan menyertakan ini dalam `shell` yang dirender sebelumnya secara statis sehingga `hero` ini akan,
00:19:21dalam kasus ini,
00:19:21menjadi bagian dari output build saya.
00:19:23Mari kita lakukan hal yang sama untuk semua hal lain di halaman ini yang dapat dibagikan.
00:19:28Misalnya, saya punya kategori fitur ini di sini.
00:19:31Mari kita lanjutkan dan lakukan hal yang sama di sana.
00:19:33Dan tambahkan direktif `use cache` dan tandai ini sebagai di-cache.
00:19:37Seperti itu.
00:19:39Dan kita bisa menghapus `suspense boundary`.
00:19:40Kita tidak akan membutuhkan ini lagi.
00:19:43Sama untuk produk unggulan.
00:19:44Mari kita tambahkan `use cache` dan tandai ini sebagai di-cache.
00:19:48Ups.
00:19:50Dan kemudian hapus `suspense boundary`.
00:19:52Jadi perhatikan berapa banyak kompleksitas yang baru saja bisa saya hapus di sini.
00:19:55Saya tidak perlu khawatir tentang `skeleton` saya,
00:19:57`cumulative layout shift` yang saya lakukan sebelumnya.
00:20:00Dan halaman tidak lagi-- atau kita tidak lagi memiliki batasan statis versus dinamis tingkat halaman ini.
00:20:07Jadi sekarang ketika saya memuat halaman ini,
00:20:10Anda akan melihat semuanya di sini di-cache kecuali untuk konten yang benar-benar spesifik pengguna ini.
00:20:16Benar.
00:20:18Jadi itu cukup keren.
00:20:19Mari kita pergi ke halaman Jelajahi dan lakukan hal yang sama di sana.
00:20:24Ya.
00:20:25Saya sudah menandai semua batas saya di sini agar Anda dapat dengan mudah memahami apa yang terjadi.
00:20:29Dan saya ingin setidaknya melakukan cache kategori-kategori ini.
00:20:33Tapi sepertinya saya mendapatkan kesalahan.
00:20:37Mungkin Anda mengenali ini.
00:20:38Jadi itu berarti saya punya `blocking route`.
00:20:40Dan saya tidak menggunakan `suspense boundary` padahal seharusnya.
00:20:43Menyegarkan ini, memang benar, ya?
00:20:46Ini sangat lambat.
00:20:47Dan itu menyebabkan masalah performa dan UX yang buruk.
00:20:50Jadi ini bagus.
00:20:51`Use cache` atau `cache components` membantu saya mengidentifikasi `blocking route` saya.
00:20:55Mari kita lihat apa yang sebenarnya terjadi di dalamnya.
00:20:57Jadi ini masalahnya, kan?
00:20:59Saya mengambil kategori-kategori ini di tingkat atas dan saya tidak punya `suspense boundary` di atasnya.
00:21:03Pada dasarnya, kita perlu membuat pilihan.
00:21:05Entah kita menambahkan `suspense boundary` di atas atau kita memilih untuk melakukan caching.
00:21:09Mari kita lakukan hal sederhana dulu dan cukup tambahkan `loading.tsx` di sini.
00:21:12Dan mari kita tambahkan halaman pemuatan di sini,
00:21:17beberapa UI `skeleton` yang bagus.
00:21:21Itu cukup bagus.
00:21:21Itu menyelesaikan kesalahan,
00:21:22tapi saya tidak punya apa pun yang berguna terjadi di halaman ini saat saya menunggu.
00:21:25Saya bahkan tidak bisa mencari.
00:21:27Jadi dengan `cache components`,
00:21:29dinamis itu seperti-- atau statis versus dinamis itu seperti sebuah skala.
00:21:33Dan terserah kita untuk memutuskan seberapa banyak statis yang kita inginkan di halaman kita.
00:21:37Jadi mari kita geser halaman ini lebih ke arah statis dan cukup hapus `loading.tsx` ini lagi.
00:21:43Dan kemudian manfaatkan pola-pola yang kita pelajari sebelumnya untuk mendorong pengambilan data ini ke dalam komponen dan menempatkannya bersama dengan UI.
00:21:50Jadi pindahkan ini ke `responsive category filters` saya di sini.
00:21:54Saya punya dua karena desain responsif.
00:21:57Saya sebenarnya bisa melanjutkan dan menambahkannya di sini.
00:22:01Ups.
00:22:03Dan impor ini.
00:22:05Saya tidak butuh `prompt` ini lagi.
00:22:06Sebenarnya, komponen saya menjadi lebih dapat disusun.
00:22:09Dan alih-alih menangguhkannya,
00:22:11mari kita tambahkan direktif `use cache`.
00:22:14Dan itu seharusnya cukup.
00:22:16Jadi perhatikan bagaimana saya dipaksa untuk lebih memikirkan di mana saya menyelesaikan `promise` saya dan sebenarnya meningkatkan arsitektur komponen saya melalui ini.
00:22:24Saya tidak perlu menangguhkan ini.
00:22:25Ini hanya akan disertakan dalam `static shell` di sini.
00:22:28Daftar produk, biarkan saya tetap segar.
00:22:35Jadi saya bisa memuat ulang itu setiap saat.
00:22:37Sedangkan kategori di bagian bawah,
00:22:39saya juga ingin melakukan cache ini.
00:22:41Jadi mari kita lanjutkan dan pergi ke `footer`.
00:22:44Dan karena saya menggunakan pola donat di sini,
00:22:47ini sebenarnya bisa di-cache meskipun berada di dalam bagian UI yang interaktif ini.
00:22:54Jadi ini tidak masalah sama sekali.
00:22:55Jadi pola itu tidak hanya bagus untuk komposisi,
00:22:57tetapi juga untuk caching.
00:22:58Saya pikir saya punya satu kesalahan lagi di sana.
00:23:03Mari kita lihat apa itu.
00:23:04Masih ada kesalahan ini.
00:23:08Ini sebenarnya karena `search frames` ini.
00:23:10`Search frames`, seperti yang kita tahu, adalah API dinamis.
00:23:12Saya tidak bisa melakukan cache ini.
00:23:13Tapi saya bisa menyelesaikannya lebih dalam untuk mengungkapkan lebih banyak UI saya dan membuatnya statis.
00:23:18Jadi mari kita lanjutkan dan pindahkan ini ke bawah,
00:23:21teruskan sebagai `promise` ke `product list`.
00:23:24Kita akan membuat ini bertipe `promise` di sini,
00:23:29seperti itu.
00:23:30Mari kita selesaikan di dalam `product list`,
00:23:33gunakan `resolved search parameters` di sini dan di sini.
00:23:36Dan karena ini ditangguhkan di sini,
00:23:38kesalahannya akan hilang.
00:23:40Jadi memuat ulang ini,
00:23:41satu-satunya hal yang memuat ulang di sini hanyalah bagian yang saya pilih secara spesifik untuk menjadi dinamis.
00:23:48Semua yang lain bisa di-cache.
00:23:49Dan itu berarti saya bisa berinteraksi dengan spanduk saya atau bahkan mencari karena bagian itu sudah dirender sebelumnya.
00:23:57Baiklah,
00:23:57mari kita lakukan halaman terakhir di sini,
00:24:01yaitu halaman produk,
00:24:02yang paling sulit dan paling penting.
00:24:05Ini sangat buruk sekarang.
00:24:08Ini sangat penting untuk platform e-commerce, tampaknya.
00:24:11Baiklah, mari kita lanjutkan dan perbaiki yang itu juga.
00:24:15Jadi di sini saya punya halaman produk ini.
00:24:18Mari kita mulai melakukan cache hanya konten yang dapat digunakan kembali di sini,
00:24:22misalnya,
00:24:22produk itu sendiri.
00:24:23Dan cukup tambahkan `use cache` di sini dan tandai ini sebagai di-cache.
00:24:27Itu seharusnya baik-baik saja.
00:24:28Itu berarti kita bisa menghapus `suspense boundary` di sini.
00:24:33Baiklah,
00:24:33dan ini tidak lagi memuat ulang pada setiap permintaan di sini,
00:24:37kan?
00:24:38Untuk detail produk, mari kita lakukan hal yang sama.
00:24:40Mari kita tambahkan `use cache`.
00:24:41Mari kita tandai sebagai di-cache dan lihat apakah itu juga akan berfungsi.
00:24:47Tidak berhasil.
00:24:48Sebenarnya, ini adalah kesalahan yang berbeda.
00:24:50Ini memberi tahu saya bahwa saya mencoba menggunakan API dinamis di dalam segmen yang di-cache ini.
00:24:54Dan itu benar.
00:24:54Saya menggunakan tombol Simpan Produk, kan?
00:24:56Itu memungkinkan saya untuk mengklik dan mengubah `saved state`.
00:25:00Jadi menurut Anda apa yang bisa kita lakukan dengan ini?
00:25:03Kita bisa menggunakan pola donat lagi.
00:25:06Sebenarnya,
00:25:06kita juga bisa menyisipkan segmen dinamis ke dalam segmen cache.
00:25:10Jadi kita menyisipkannya seperti sebelumnya,
00:25:11tetapi dengan cache.
00:25:12Jadi ini cukup keren.
00:25:14Mari kita lanjutkan dan tambahkan `children` di sini seperti itu.
00:25:19Dan ini akan menghilangkan kesalahan.
00:25:21Dan saya bisa membungkus ini di sekitar satu segmen dinamis halaman saya di sini,
00:25:26menghapus `suspense boundary`,
00:25:28dan menambahkan UI `bookmark` yang sangat kecil untuk satu bagian dinamis halaman itu.
00:25:34Dan mari kita lihat bagaimana tampilannya sekarang.
00:25:40Jadi perhatikan bagaimana hampir seluruh UI tersedia,
00:25:43tetapi saya punya satu bagian kecil yang dinamis,
00:25:46dan itu tidak masalah.
00:25:47Semua yang lain masih ada.
00:25:48Dan mari kita biarkan ulasan tetap dinamis karena kita bisa menjaganya tetap segar.
00:25:53Masih ada satu kesalahan lagi.
00:25:54Mari kita cepat atasi itu.
00:25:56Lagi, ini adalah `params`.
00:25:58Saya mendapatkan bantuan bahwa saya perlu membuat pilihan,
00:26:01entah menambahkan `loading fallback` atau melakukan cache ini.
00:26:04Mari kita gunakan `generate static params` dalam kasus ini.
00:26:07Agak tergantung pada kasus penggunaan Anda dan set data Anda.
00:26:10Tapi untuk kasus ini,
00:26:11saya hanya akan menambahkan beberapa halaman yang sudah dirender sebelumnya dan kemudian cukup melakukan cache sisanya saat dibuat oleh pengguna.
00:26:17Dan ini akan menghilangkan kesalahan saya di sini.
00:26:20Jadi saya pikir saya sebenarnya sudah selesai dengan refactor saya.
00:26:22Mari kita lanjutkan dan lihat versi yang sudah di-deploy dan lihat seperti apa tampilannya.
00:26:26Jadi saya baru saja mendeploy ini di Vercel.
00:26:27Dan ingat,
00:26:29saya sengaja memperlambat banyak pengambilan data di sini.
00:26:35Dan tetap saja,
00:26:36ketika saya memuat halaman ini pada awalnya,
00:26:39semuanya sudah tersedia.
00:26:40Satu-satunya hal di sini hanyalah beberapa segmen dinamis seperti diskon dan untuk Anda.
00:26:46Sama dengan `browse all`.
00:26:47Semua UI sudah tersedia.
00:26:50Dan untuk produk itu sendiri, rasanya instan.
00:26:54Dan ingat,
00:26:55lagi,
00:26:55bahwa semua segmen cache ini akan disertakan dengan `static shell` dengan `partial pre-rendering`.
00:27:00Dan itu bisa di-prefetch menggunakan `prefetching` yang ditingkatkan di `client router` Next 16 yang baru.
00:27:05Jadi itu berarti setiap navigasi hanya-- rasanya sangat cepat,
00:27:09kan?
00:27:09Baiklah,
00:27:10untuk meringkas,
00:27:11dengan `cache components`,
00:27:14tidak ada lagi statis versus dinamis.
00:27:17Dan kita tidak perlu menghindari API dinamis atau mengkompromikan konten dinamis.
00:27:28Dan kita bisa melewati `hack` dan solusi kompleks ini menggunakan beberapa strategi pengambilan data hanya untuk satu-- `cache hit` ini,
00:27:36seperti yang saya tunjukkan.
00:27:37Jadi di Next.js modern,
00:27:38dinamis versus statis adalah sebuah skala.
00:27:40Dan kita memutuskan seberapa banyak statis yang kita inginkan di aplikasi kita.
00:27:43Dan selama kita mengikuti pola-pola tertentu,
00:27:45kita bisa memiliki satu model mental,
00:27:47yang performan,
00:27:48dapat disusun,
00:27:49dan skalabel secara default.
00:27:50Jadi mari kita kembali ke slide.
00:27:53Jadi jika Anda belum-- kita belum terkesan dengan kecepatan itu,
00:27:55ini adalah skor Lighthouse.
00:27:56Jadi saya mengumpulkan beberapa data lapangan dengan Vercel Speed Insights.
00:28:00Jadi kita punya skor 100 di semua halaman terpenting,
00:28:02halaman beranda,
00:28:03halaman produk,
00:28:04dan daftar produk,
00:28:05meskipun halaman-halaman tersebut sangat dinamis.
00:28:08Jadi mari kita akhirnya meringkas pola-pola yang akan memastikan skalabilitas dan performa di aplikasi Next.js dan memungkinkan kita memanfaatkan inovasi terbaru serta mendapatkan skor seperti ini.
00:28:18Jadi pertama,
00:28:19kita bisa menyempurnakan arsitektur kita dengan menyelesaikan `promise` jauh di dalam pohon komponen dan mengambil data secara lokal di dalam komponen menggunakan `React Cache` untuk menduplikasi pekerjaan.
00:28:28Kita bisa menghindari penerusan `prop` yang berlebihan ke komponen klien dengan menggunakan `context providers` yang dikombinasikan dengan `React Use`.
00:28:35Kedua,
00:28:35kita bisa menyusun komponen klien yang melayani menggunakan pola donat untuk mengurangi JavaScript sisi klien,
00:28:40menjaga pemisahan kekhawatiran yang jelas,
00:28:42dan memungkinkan penggunaan kembali komponen.
00:28:43Dan pola ini akan lebih lanjut memungkinkan kita untuk melakukan cache komponen server kita yang disusun nanti.
00:28:50Dan terakhir,
00:28:50kita bisa melakukan cache dan pra-render dengan `use cache` baik berdasarkan halaman,
00:28:54komponen,
00:28:54atau fungsi untuk menghilangkan pemrosesan yang berlebihan,
00:28:56meningkatkan performa dan SEO,
00:28:58dan membiarkan `partial pre-rendering` merender segmen-segmen aplikasi ini secara statis.
00:29:01Dan jika konten kita benar-benar dinamis,
00:29:03kita bisa menangguhkannya dengan `loading fallback` yang sesuai.
00:29:07Dan ingat bahwa semua ini saling terhubung.
00:29:09Jadi semakin baik arsitektur Anda,
00:29:10semakin mudah untuk menyusun,
00:29:11dan semakin mudah untuk melakukan cache dan pra-render dengan hasil terbaik.
00:29:15Misalnya,
00:29:15menyelesaikan API dinamis jauh di dalam pohon akan memungkinkan Anda membuat `static shell` yang dirender sebagian lebih besar.
00:29:22Dan dengan itu,
00:29:22ini adalah `repo` dari versi aplikasi yang sudah selesai.
00:29:25Ada begitu banyak hal yang bahkan tidak saya tunjukkan di sana yang bisa Anda lihat.
00:29:29Dan Anda bisa memindai kode QR untuk menemukan media sosial saya di sana bersama dengan `repo` jika Anda tidak ingin mengambil gambar dan mengetiknya sendiri.
00:29:36Jadi ya, itu saja dari saya.
00:29:37Terima kasih Next.js Conf telah mengundang saya di sini.
00:29:39[MUSIK BERMAIN]

Key Takeaway

Dengan Next.js 16, pengembang dapat mencapai skalabilitas dan performa tinggi di aplikasi yang dinamis sekalipun melalui pola komposisi cerdas, caching granular menggunakan 'use cache', dan arsitektur yang terstruktur dengan baik.

Highlights

Next.js 16 memperkenalkan direktif 'use cache' yang memungkinkan caching granular pada tingkat halaman, komponen, atau fungsi, menghilangkan batasan statis vs. dinamis penuh.

Pola 'Donut Pattern' memungkinkan pembungkus komponen sisi klien di sekitar konten yang dirender server, mengurangi JavaScript sisi klien dan menjaga pemisahan kekhawatiran.

Mengatasi 'prop drilling' dengan memindahkan pengambilan data ke dalam komponen server yang menggunakannya, memanfaatkan 'React Cache' dan 'React Use' untuk meningkatkan komposisi dan penggunaan kembali.

'Cache components' membantu mengidentifikasi rute pemblokiran dan mendorong pengembang untuk mengoptimalkan arsitektur komponen dengan memindahkan pengambilan data ke tingkat yang lebih dalam.

Dengan 'partial pre-rendering', segmen yang di-cache dapat disertakan dalam 'shell' statis yang dirender sebelumnya, menghasilkan pemuatan halaman yang sangat cepat bahkan untuk aplikasi yang sangat dinamis.

Timeline

Pendahuluan dan Tujuan Presentasi

Aurora, seorang pengembang web dari Norwegia, memperkenalkan dirinya dan topik presentasi. Dia akan membahas pola-pola komposisi, caching, dan arsitektur di Next.js modern yang dirancang untuk memastikan skalabilitas dan performa aplikasi. Pembahasan ini sangat relevan bagi pengembang yang ingin mengoptimalkan aplikasi Next.js mereka. Tujuannya adalah untuk memberikan wawasan tentang bagaimana membangun aplikasi yang lebih cepat dan mudah dipelihara.

Konsep Rendering Statis

Bagian ini menyegarkan kembali konsep rendering statis di Next.js app router. Rendering statis memungkinkan pembuatan situs web yang lebih cepat karena konten dirender sebelumnya, dapat di-cache, dan didistribusikan secara global, seperti contoh situs web Next.js Conf. Manfaat utamanya meliputi pengurangan beban server dan peningkatan SEO karena konten sudah tersedia saat halaman dimuat. Ini adalah fondasi penting untuk memahami bagaimana Next.js mengoptimalkan performa.

Konsep Rendering Dinamis

Selanjutnya, dijelaskan rendering dinamis yang memungkinkan aplikasi menampilkan data real-time atau yang sering diperbarui, serta menyajikan konten yang dipersonalisasi seperti dasbor pengguna (contoh: dasbor Vercel). Dengan rendering dinamis, aplikasi dapat mengakses informasi yang hanya diketahui pada saat permintaan, seperti identitas pengguna yang sedang mengakses. Ini penting untuk fitur interaktif dan personalisasi dalam aplikasi web modern.

API yang Memicu Rendering Dinamis

Dijelaskan API spesifik yang dapat menyebabkan halaman dirender secara dinamis. Ini termasuk penggunaan 'params' dan 'searchParams', membaca 'cookie' dan 'header' permintaan masuk, serta penggunaan 'fetch' dengan konfigurasi cache data 'no-store'. Penting untuk dicatat bahwa 'params' dapat memungkinkan pra-rendering dengan 'static params', sementara 'headers' atau 'cookies' tidak dapat di-cache saat build. Pemahaman ini krusial untuk mengontrol perilaku rendering halaman.

Keterbatasan Next.js Versi Sebelumnya dan Masalah Campuran Konten

Pada versi Next.js sebelumnya, sebuah halaman akan dirender secara statis penuh atau dinamis penuh; satu API dinamis akan membuat seluruh halaman menjadi dinamis. Hal ini menyebabkan pemrosesan berlebihan di server untuk konten yang jarang berubah, tidak optimal untuk performa, dan membuang-buang sumber daya. Contoh aplikasi e-commerce dengan campuran konten statis dan dinamis menyoroti masalah ini. Keterbatasan ini menjadi pendorong inovasi di Next.js modern.

Pengenalan Direktif 'use cache' di Next.js 16

Untuk mengatasi masalah rendering campuran, direktif 'use cache' diperkenalkan di Next.js 16. Dengan ini, halaman tidak lagi dipaksa menjadi statis atau dinamis secara keseluruhan; keduanya bisa. 'use cache' memungkinkan caching yang dapat disusun pada tingkat halaman, komponen React, atau fungsi, serta mendukung 'partial pre-rendering' untuk menyertakan segmen cache sebagai bagian dari 'shell' statis. Ini adalah perubahan paradigma yang signifikan untuk optimasi.

Pengaturan Demo dan Identifikasi Masalah Umum

Presenter memulai demo dengan aplikasi e-commerce sederhana yang sengaja diperlambat untuk menunjukkan masalah performa. Aplikasi ini memiliki fitur seperti produk unggulan, kategori, halaman produk, dan dasbor pengguna yang dipersonalisasi. Masalah umum yang akan diatasi meliputi 'prop drilling' yang dalam, JavaScript sisi klien yang berlebihan, komponen besar dengan banyak tanggung jawab, dan kurangnya rendering statis. Tujuan demo adalah meningkatkan aplikasi ini agar lebih cepat, skalabel, dan mudah dipelihara.

Mengatasi 'Prop Drilling' dengan Komponen Server dan 'React Cache'

Bagian ini menunjukkan cara mengatasi 'prop drilling' yang dalam dengan memindahkan pengambilan data ke dalam komponen server yang menggunakannya. Dengan memanfaatkan 'React cache' dan 'React use' bersama 'auth provider' kustom, nilai 'loggedIn' dapat diakses secara lokal tanpa perlu meneruskan 'prop' secara berjenjang. Penggunaan 'Suspense' juga diterapkan untuk menangguhkan komponen asinkron, memastikan halaman tidak terblokir. Pola ini meningkatkan komposisi dan penggunaan kembali komponen secara signifikan.

Mengurangi JavaScript Sisi Klien dengan 'Donut Pattern'

Masalah JavaScript sisi klien yang berlebihan diatasi menggunakan 'Donut Pattern'. Pola ini melibatkan pembungkus logika UI sisi klien ('banner container') di sekitar konten yang dirender server ('children'). Ini memungkinkan komponen server untuk tetap server-rendered sambil menyediakan interaktivitas klien yang diperlukan, seperti tombol 'dismissed' atau animasi (contoh: Framer Motion). Penerapan pola ini pada kategori di 'footer' dengan fitur 'showMore' juga ditunjukkan, menjaga pemisahan kekhawatiran dan mengurangi JS sisi klien.

Strategi Rendering Statis yang Kurang Optimal Sebelumnya

Presenter membahas masalah kurangnya strategi rendering statis yang efektif, di mana semua halaman menjadi dinamis karena satu API dinamis di 'root layout' (misalnya, profil pengguna yang menggunakan 'cookie'). Solusi lama seperti 'route groups' atau 'request context param' dengan 'generate static params' dianggap terlalu kompleks atau tidak cukup membantu untuk aplikasi yang lebih besar. Ini menyoroti kebutuhan akan pendekatan yang lebih sederhana dan efisien untuk caching.

Mengaktifkan 'cache components' dan Menerapkan 'use cache' di Halaman Beranda

Solusi modern dimulai dengan mengaktifkan 'cache components' di 'next.config.js' Next.js 16, yang secara default membuat semua panggilan asinkron menjadi dinamis dan memberikan direktif 'use cache'. Direktif ini kemudian diterapkan secara granular pada bagian-bagian statis halaman beranda seperti 'hero', kategori unggulan, dan produk unggulan. Dengan 'use cache', bagian-bagian ini dirender statis dan disertakan dalam 'shell' statis melalui 'partial pre-rendering', menghilangkan kebutuhan akan 'Suspense' dan 'skeleton' UI.

Penerapan 'use cache' dan 'Donut Pattern' di Halaman 'Jelajahi Semua'

Pada halaman 'Jelajahi Semua', 'cache components' membantu mengidentifikasi rute pemblokiran karena pengambilan data kategori di tingkat atas tanpa 'Suspense'. Solusi yang diterapkan adalah memindahkan pengambilan data ke dalam komponen ('responsive category filters') dan menerapkan 'use cache' pada komponen tersebut, sehingga meningkatkan arsitektur. 'Donut Pattern' juga digunakan untuk kategori di 'footer' agar konten yang di-cache dapat berada di dalam UI interaktif. Masalah 'searchParams' (API dinamis) diatasi dengan memindahkan resolusinya lebih dalam ke 'product list' dan meneruskannya sebagai 'promise'.

Penerapan 'use cache' dan 'Donut Pattern' di Halaman Produk

Halaman produk, yang paling kompleks, juga dioptimalkan. 'use cache' diterapkan pada produk itu sendiri dan detail produk. Ketika 'use cache' diterapkan pada segmen yang berisi API dinamis (tombol 'Simpan Produk'), kesalahan muncul. Ini diatasi dengan 'Donut Pattern' untuk menyisipkan segmen dinamis (tombol) ke dalam segmen yang di-cache, memungkinkan sebagian besar halaman tetap statis. Untuk 'params', 'generate static params' digunakan untuk pra-render beberapa halaman dan meng-cache sisanya saat dibuat oleh pengguna.

Hasil Demo dan Peningkatan Performa

Setelah refaktor, aplikasi yang di-deploy di Vercel menunjukkan peningkatan performa yang signifikan. Meskipun pengambilan data sengaja diperlambat, UI memuat secara instan, dengan hanya segmen dinamis yang spesifik pengguna yang di-stream. 'Partial pre-rendering' menyertakan segmen yang di-cache dalam 'shell' statis, dan 'prefetching' yang ditingkatkan di 'client router' Next.js 16 membuat navigasi terasa sangat cepat. Skor Lighthouse yang sempurna (100) pada halaman-halaman penting membuktikan efektivitas pola-pola ini.

Ringkasan Pola dan Kesimpulan

Presenter menyimpulkan bahwa dengan 'cache components', konsep statis vs. dinamis menjadi sebuah skala, memungkinkan pengembang untuk memutuskan seberapa banyak konten statis yang diinginkan. Tiga pola utama ditekankan: menyempurnakan arsitektur dengan pengambilan data lokal dan menghindari 'prop drilling', menyusun komponen klien yang melayani dengan 'Donut Pattern' untuk mengurangi JS sisi klien, dan melakukan cache/pra-render dengan 'use cache' untuk performa dan SEO. Semua pola ini saling terhubung, menghasilkan model mental yang performan, dapat disusun, dan skalabel secara default.

Community Posts

View all posts