Komponen caching di Next.js: Mempercepat halaman dengan pra-render sebagian

 – Beragampengetahuan
10 mins read

Komponen caching di Next.js: Mempercepat halaman dengan pra-render sebagian – Beragampengetahuan

Performa rendering pada aplikasi web seringkali dibatasi oleh pekerjaan server yang tidak dapat diselesaikan dengan segera. Akuisisi data, personalisasi, dan agregasi backend semuanya membutuhkan waktu. Di banyak aplikasi, pekerjaan ini memblokir seluruh halaman, meninggalkan pengguna dengan layar kosong hingga semuanya selesai.

Komponen caching di Next.js: Mempercepat halaman dengan pra-render sebagian

Next.js secara tradisional mengatasi masalah ini dengan menggunakan model statis secara default. Rute bisa statis atau dinamis, dan keputusannya berlaku untuk seluruh halaman. Ini bekerja dengan baik untuk kasus-kasus sederhana, namun seiring berkembangnya aplikasi, hal ini menjadi terbatas. Sebagian besar halaman nyata menggabungkan data yang dapat diprediksi dengan data khusus permintaan, namun halaman tersebut dipaksa ke dalam mode rendering tunggal.

Next.js 16 memperkenalkan komponen caching untuk mengatasi keterbatasan ini. Komponen caching beroperasi pada tingkat komponen dan dibangun di atas pra-render parsial. Pra-perenderan sebagian memungkinkan shell halaman dirender dengan segera, sementara bagian yang lebih lambat ditunda. Komponen caching memperluas model ini dengan memungkinkan Anda mengontrol bagian halaman mana yang dapat digunakan kembali tanpa memblokir bagian lainnya.

Dalam artikel ini, kita akan melihat bagaimana komponen caching masuk ke dalam pipeline rendering Next.js, dan bagaimana komponen tersebut mengubah cara konten statis dan dinamis hidup berdampingan di halaman yang sama.

Contents

🚀 Berlangganan Buletin Putar Ulang

memutar ulang adalah buletin mingguan untuk para pemimpin pengembangan dan teknik.

Diterbitkan setiap minggu, ini adalah panduan pilihan Anda untuk percakapan paling penting tentang pengembangan front-end, alat AI yang sedang berkembang, dan keadaan perangkat lunak modern.

Sekilas tentang pra-rendering parsial (PPR)

Halaman modern jarang hanya menangani satu jenis data. Navigasi dan tata letak sering kali dapat diprediksi, data katalog atau konten terkadang berubah, dan data personalisasi atau sesi harus dihitung berdasarkan permintaan. Ketika semua pekerjaan ini ditangani dalam satu render pass, operasi paling lambat menentukan kapan sesuatu dapat ditampilkan.

Pra-perenderan sebagian menghindari hal ini dengan mengizinkan laman dirender secara bertahap. Shell statis dikirim terlebih dahulu untuk membangun struktur, sedangkan bagian dinamis dibungkus dalam batas Suspense dan dirender secara independen:

Sebagian telah dipra-render
Sebagian telah dipra-render

Saat bagian ini selesai dirender, bagian tersebut dialirkan ke klien tanpa memblokir halaman lainnya. Pengguna melihat kemajuan, bukan layar kosong.

Pra-perenderan sebagian meningkatkan cara penayangan laman, namun tidak menentukan seberapa sering tugas server harus dijalankan atau apakah hasilnya dapat digunakan kembali. Keterbatasan ini membuat komponen caching diperlukan.

Memperkenalkan komponen caching

Meskipun pra-perenderan sebagian meningkatkan cara penayangan laman, hal ini tidak mengubah apa yang terjadi di server. Saat permintaan datang, bagian dinamis masih berjalan. Jika suatu bagian mengambil data yang sama pada setiap permintaan, pekerjaan akan diulangi meskipun hasilnya sama.

Ini adalah celah yang diatasi oleh komponen caching. Dengan komponen cache, keputusan cache dipindahkan ke tingkat komponen. Daripada memperlakukan seluruh rute sebagai statis atau dinamis, Anda menandai bagian tertentu dari UI sebagai dapat disimpan dalam cache dan membiarkan sisanya sebagai dinamis. Hal ini memungkinkan untuk menggunakan kembali keluaran yang dirender oleh server yang dapat diprediksi tanpa memengaruhi bagian khusus permintaan:

Aplikasi praktis komponen caching
Menjalankan komponen caching

Gambar ini menunjukkan halaman yang sama yang dirender melalui dua permintaan terpisah:

Persyaratan 1 Menunjukkan pertama kali halaman dirender. Semua bagian dijalankan di server. tanda komponen C Memenuhi syarat untuk caching, sehingga outputnya dihitung dan disimpan. tanda komponen D Bersifat dinamis dan dijalankan sebagai bagian dari permintaan.

Persyaratan 2 Mewakili permintaan selanjutnya untuk halaman yang sama. Komponen yang di-cache tidak akan dijalankan lagi. Output yang diberikan sebelumnya digunakan kembali. Komponen dinamis masih berjalan di server karena bergantung pada data khusus permintaan.



Tata letak halaman tidak berubah antar permintaan. Yang berubah adalah siklus hidup masing-masing bagiannya. Komponen caching memungkinkan bagian halaman yang dapat diprediksi untuk digunakan kembali di seluruh permintaan, sementara bagian dinamis terus berjalan setiap saat.

Konfigurasikan komponen caching

Untuk mendemonstrasikan komponen caching sepenuhnya, ada baiknya jika Anda memahami terlebih dahulu bagaimana perilaku halaman tanpa komponen caching. Untuk melakukan ini, saya membangun aplikasi menggunakan cara tradisional. Anda dapat menemukan repositori GitHub terkait di sini.

Versi ini tidak menggunakan komponen caching dalam bentuk apapun. Semuanya terjadi dalam satu server rendering. Anda dapat mengonfirmasinya di next.config.ts:

// next.config.ts
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
  /* config options here */
};
export default nextConfig;

Pada halaman itu sendiri, rendering dinamis secara eksplisit bersifat wajib. Hal ini memastikan bahwa logika server baru dijalankan pada setiap permintaan dan tidak ada yang digunakan kembali.

import ProductGrid from '@/components/product-grid';        // 2 seconds
import Recommendations from '@/components/recommendations'; // 3 seconds
import Orders from '@/components/orders';                   // 2 seconds

Anda akan melihat bahwa ada tiga sumber data terpisah:

  • produk, memerlukan waktu sekitar dua detik
  • Direkomendasikan, membutuhkan waktu sekitar tiga detik
  • Pesanan terbaru, membutuhkan waktu sekitar dua detik

Karena panggilan-panggilan ini ditunggu satu demi satu, total waktu tunggu untuk server kira-kira tujuh detik. Lebih penting lagi, pernyataan return hanya berjalan setelah permintaan terakhir selesai. Sampai saat itu tiba, React tidak punya apa pun untuk dirender. Untuk mengonfirmasi hal ini, jalankan perintah berikut untuk memulai aplikasi:

npm run dev

Menavigasi ke hal pertama yang Anda perhatikan adalah tidak ada apa-apa. Tidak ada judul. Tidak ada tata letak. Tidak ada status pemuatan. Browser menjadi kosong:

Konfigurasikan komponen caching

Saat halaman akhirnya dirender, halaman tersebut akan selesai dalam waktu sekitar tujuh detik. Penundaan ini terjadi karena halaman disusun untuk menunggu data paling lambat sebelum merender apa pun. Dalam praktiknya, sebagian besar UI tidak perlu menunggu. Header, footer, dan bagian halaman lainnya yang tidak bergantung pada data lambat dapat dirender secara instan.

Di sinilah peran pra-render parsial. Pra-render parsial memungkinkan halaman merender shell statis terlebih dahulu, sedangkan bagian yang lebih lambat ditunda. Ini memungkinkan Anda untuk mencampur jenis rendering pada halaman yang sama. Namun, ia mempunyai keterbatasan. Meskipun porsi yang tertunda dapat dialirkan, porsi tersebut tetap dihitung ulang pada setiap permintaan. Pra-perenderan sebagian meningkatkan pengiriman, namun tidak memungkinkan penyimpanan bagian dinamis ini dalam cache. Keterbatasan ini mengarahkan kita untuk menggunakan komponen caching.

Sekarang mari kita konfigurasikan komponen caching.

Pertama, kita perlu mengkonfigurasi komponen caching untuk mengaktifkannya karena masih dalam tahap percobaan. Membuka next.config.ts dan diperbarui sebagai berikut:

import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
  experimental: {
    useCache: true,
  },
};
export default nextConfig;

Bendera ini memungkinkan use cache direktif dan memberitahu Next.js untuk mengizinkan caching di tingkat komponen.

Selanjutnya, kita memerlukan tempat untuk menentukan masa pakai data cache. Dalam aplikasi, semuanya diambil ulang pada setiap permintaan. Kami ingin mengubahnya dengan komponen caching sehingga kami dapat mengontrol kesegaran secara eksplisit.


Lebih banyak artikel bagus dari beragampengetahuan:


Buat file baru dilib/cache-config.ts:

export const cacheProfiles = {
  products: {
    stale: 3600,      // 1 hour
    revalidate: 7200, // 2 hours
    expire: 86400,    // 24 hours
  },
};

Perlu dicatat bahwa file itu sendiri tidak mengubah perilakunya. Ini hanya memusatkan strategi caching sehingga dapat digunakan kembali di seluruh komponen.

Jadikan jaringan produk dapat di-cache

Membuka components/product-grid.tsx dan mengganti isinya dengan versi cache berikut:

'use cache';
import { fetchProducts } from '@/lib/demo-data';
import { cacheProfiles } from '@/lib/cache-config';
export async function cacheLife() {
 return cacheProfiles.products;
}
export default async function ProductGrid() {
 const products = await fetchProducts();
 return (
   <section style={{ marginBottom: '3rem' }}>
     <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '1.5rem' }}>
       <h2 style={{ fontSize: '1.5rem', fontWeight: 'bold' }}>Products</h2>
     </div>
     <div className="grid grid-4">
       {products.map(product => (
         <div key={product.id} className="card fade-in">
           <div style={{ fontSize: '3rem', marginBottom: '0.5rem' }}>{product.image}</div>
           <h3 style={{ fontSize: '1.125rem', fontWeight: '600', marginBottom: '0.25rem' }}>
             {product.name}
           </h3>
           <p style={{ color: '#888', fontSize: '0.875rem', marginBottom: '0.5rem' }}>
             {product.category}
           </p>
           <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
             <span style={{ fontSize: '1.25rem', fontWeight: 'bold', color: '#10b981' }}>
               ${product.price}
             </span>
             <span style={{ fontSize: '0.875rem', color: '#888' }}>
               Stock: {product.stock}
             </span>
           </div>
         </div>
       ))}
     </div>
   </section>
 );
}

Bagian atas file adalah 'use cache'Signal, yang memberi tahu Next.js bahwa komponen dapat digunakan kembali alih-alih dihitung ulang pada setiap permintaan. Tanpanya, komponen akan berperilaku persis seperti sebelumnya dan berjalan setiap kali halaman dirender.

Kami juga menambahkan fungsi cacheLife(), di sinilah kami memutuskan berapa lama grid produk harus dipertahankan. Karena produk tidak berubah setiap ada permintaan, masuk akal untuk menggunakannya kembali selama jangka waktu tertentu daripada terus-menerus mengambilnya kembali. Daripada menyimpan seluruh halaman dalam cache, pendekatan ini memungkinkan kita untuk menyimpan cache hanya pada bagian-bagian yang mendapat manfaat darinya.

Gunakan Suspense untuk mengisolasi bagian yang lambat

Setelah menyimpan grid produk dalam cache, tujuan selanjutnya adalah membuat halaman dirender secepat mungkin, dan hanya membiarkan bagian yang mengandalkan data lambat untuk menunggu. Di sinilah Suspense berperan. Ini memungkinkan kita menandai bagian halaman yang dapat dimuat nanti, jadi ketika bagian tersebut masih diurai di server, React dapat mengirim sisa halaman ke browser dan mengisi kekosongan setelahnya.

Untuk membuat penundaan terlihat, kita perlu menampilkan sesuatu sebagai pengganti konten sebenarnya.

Buat file baru di components/loading-skeleton.tsx:

export default function LoadingSkeleton({ count = 4 }: { count?: number }) {
  return (
    <div className="grid grid-4">
      {Array.from({ length: count }).map((_, i) => (
        <div key={i} className="card skeleton" />
      ))}
    </div>
  );
}

Kode di atas menampilkan kisi-kisi kartu kecil yang kira-kira sesuai dengan bentuk ubin produk di UI, sehingga halaman tidak terasa kosong saat kita menunggu data sebenarnya tiba.

Sekarang buka app/page.tsxdan ganti isinya dengan yang berikut ini:

import './globals.css';
import { Suspense } from 'react';
import { getTimestamp } from '@/lib/demo-data';
import LoadingSkeleton from '@/components/loading-skeleton';
import ProductGrid from '@/components/product-grid';              
import Recommendations from '@/components/recommendations';       
import Orders from '@/components/orders';                         
export const dynamic="force-dynamic";
export default function CacheApp() {
  const timestamp = getTimestamp();
  return (
    <>
      <div className="container" style={{ padding: '2rem 1rem' }}>
        {/* Header Banner */}
        <div style={{ 
          marginBottom: '2rem', 
          padding: '1.5rem', 
          background: '#065f46', 
          borderRadius: '12px', 
          border: '2px solid #10b981' 
        }}>
          <h1 style={{ fontSize: '2rem', fontWeight: 'bold', marginBottom: '0.5rem' }}>
            Ecommerce App
          </h1>
          <p style={{ fontSize: '1rem', color: '#86efac', marginBottom: '0.5rem' }}>
            Cached content renders immediately, while dynamic sections load progressively.
          </p>
          <p style={{ fontSize: '0.875rem', color: '#d1fae5', fontFamily: 'monospace' }}>
            Rendered at: {timestamp}
          </p>
        </div>
        <Suspense fallback={
          <section style={{ marginBottom: '3rem' }}>
            <div style={{ marginBottom: '1.5rem' }}>
              <h2 style={{ fontSize: '1.5rem', fontWeight: 'bold' }}>Products</h2>
              <p style={{ color: '#888', fontSize: '0.875rem' }}>Loading products...</p>
            </div>
            <LoadingSkeleton count={4} />
          </section>
        }>
          <ProductGrid />
        </Suspense>
        <Suspense fallback={
          <section style={{ marginBottom: '3rem' }}>
            <div style={{ marginBottom: '1.5rem' }}>
              <h2 style={{ fontSize: '1.5rem', fontWeight: 'bold' }}>Recommended for You</h2>
              <p style={{ color: '#888', fontSize: '0.875rem' }}>Loading personalized recommendations...</p>
            </div>
            <LoadingSkeleton count={3} />
          </section>
        }>
          <Recommendations userId="user-123" />
        </Suspense>
        <Suspense fallback={
          <section style={{ marginBottom: '3rem' }}>
            <div style={{ marginBottom: '1.5rem' }}>
              <h2 style={{ fontSize: '1.5rem', fontWeight: 'bold' }}>Recent Orders</h2>
              <p style={{ color: '#888', fontSize: '0.875rem' }}>Loading your orders...</p>
            </div>
            <LoadingSkeleton count={3} />
          </section>
        }>
          <Orders userId="user-123" />
        </Suspense>
        <div style={{ 
          padding: '2rem', 
          background: '#1a1a1a', 
          borderRadius: '12px', 
          border: '1px solid #2a2a2a', 
          textAlign: 'center' 
        }}>
          <h3 style={{ fontSize: '1.25rem', marginBottom: '1rem', color: '#10b981' }}>
            Improved User Experience
          </h3>
          <p style={{ color: '#888', maxWidth: '600px', margin: '0 auto' }}>
            The page renders immediately with cached content, while user-specific sections
            load progressively without blocking the rest of the UI.
          </p>
        </div>
      </div>
    </>
  );
}

Kini, halaman tidak lagi dipaksa menunggu setiap sumber data sebelum dirender. Judul muncul seketika, dan setiap bagian berdasarkan data dimuat dengan kecepatannya sendiri. Kisi produk dibungkus dalam Suspense, sehingga halaman dirender bahkan ketika dimuat dalam keadaan dingin, dan keluaran cache-nya segera diurai pada permintaan berikutnya. Bagian rekomendasi dan pesanan masih berjalan berdasarkan permintaan, namun tidak lagi memblokir UI lainnya. Sebaliknya, placeholder muncul terlebih dahulu dan diganti segera setelah data siap.

Meluncurkan ulang aplikasi dan menavigasi ke waktu ini, judul dan kisi produk segera muncul, dan pengatur waktu mengonfirmasi bahwa konten pertama segera ditampilkan. Rekomendasi dan pesanan tidak lagi memblokir halaman. Kerangka mereka muncul pertama kali, dengan konten sebenarnya mengalir ketika sudah siap:

Perbandingan kinerja komponen cache

Perbandingan kinerja

Pengguna tidak merasakan arsitekturnya. Mereka mengalami waktu pemuatan. Tabel berikut merangkum perilaku kedua versi selama pemuatan halaman:

Metrik aplikasi tradisional Komponen cache
waktu konten pertama ~7 detik <100 milidetik
Pengalaman awal layar hitam Antarmuka pengguna instan
Pemblokiran server total ~7 detik mendekati nol
katalog produk Blokir rendering (~2 detik) Di-cache dan akan berlaku segera setelah memuat ulang
saran Blokir halaman (~3 detik) aliran masuk
Memesan Blokir halaman (~2 detik) aliran masuk
membuat model semua atau tidak sama sekali kemajuan
Waktu muat yang dirasakan lambat dengan cepat

Praktik terbaik untuk menggunakan komponen caching

Komponen caching sangat kuat, namun berfungsi paling baik bila diterapkan dengan hati-hati. Berikut beberapa praktik terbaik saat menggunakan komponen caching:

  • Jangan gabungkan API runtime dengan komponen caching
  • Jaga agar batasan ketegangan tetap jelas dan berlapis
  • Hanya bagian deterministik cache (misalnya daftar produk, navigasi)
  • Pantau ukuran dan siklus hidup cache untuk menghindari data basi atau penyegaran yang lambat
  • Untuk pembaruan terkontrol, lebih baik menggunakan tag daripada penyegaran manual

sebagai kesimpulan

Komponen caching mengubah cara pengambilan keputusan rendering di Next.js. Daripada memilih antara statis dan dinamis di tingkat halaman, Anda dapat memutuskan di tingkat komponen bagian UI mana yang harus digunakan kembali dan bagian mana yang harus tetap spesifik permintaan.

Dalam contoh yang kami tunjukkan, peningkatan tidak datang dari penulisan ulang aplikasi atau perubahan model data. Ini berasal dari pemisahan pekerjaan yang dapat diprediksi dari pekerjaan khusus pengguna dan memungkinkan masing-masing pekerjaan dirender pada timeline-nya sendiri. Komponen caching mengurangi pekerjaan duplikat server, sementara Suspense memastikan bahwa bagian yang lebih lambat tidak lagi memblokir sisa halaman.

Untuk detail lebih lanjut tentang komponen caching, pra-render sebagian, dan API terkait, lihat dokumentasi resmi Next.js.

beragampengetahuan: Tampilan komprehensif aplikasi produksi Next.js

Men-debug aplikasi berikutnya bisa jadi sulit, terutama ketika pengguna mengalami masalah yang sulit untuk direproduksi. Jika Anda tertarik untuk memantau dan melacak status, menampilkan kesalahan JavaScript secara otomatis, dan melacak permintaan jaringan yang lambat serta waktu pemuatan komponen, cobalah beragampengetahuan.

beragampengetahuan menangkap log konsol, kesalahan, permintaan jaringan, dan catatan DOM dengan piksel sempurna dari sesi pengguna dan memungkinkan Anda memutarnya kembali saat pengguna melihatnya, sehingga tidak perlu menebak-nebak mengapa kesalahan terjadi – Kompatibel dengan semua kerangka kerja.

Galileo AI dari beragampengetahuan memantau sesi untuk Anda, secara instan mengidentifikasi dan menjelaskan kesulitan pengguna dalam memantau keseluruhan pengalaman produk secara otomatis.

Paket middleware beragampengetahuan Redux menambahkan lapisan visibilitas tambahan ke sesi pengguna Anda. beragampengetahuan mencatat semua operasi dan status di penyimpanan Redux.

Spanduk Uji Coba Gratis Dasbor beragampengetahuan

Modernkan cara Anda men-debug aplikasi Next.js – mulai memantau secara gratis.

rencana pengembangan website



metode pengembangan website

jelaskan beberapa rencana untuk pengembangan website, proses pengembangan website, kekuatan dan kelemahan bisnis pengembangan website
, jasa pengembangan website, tahap pengembangan website, biaya pengembangan website

#Komponen #caching #Next.js #Mempercepat #halaman #dengan #prarender #sebagian

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *