Cara Mengatasi Loading Lambat di Next.js Akibat API Eksternal (Studi Kasus: Google Analytics View Counter)

PE
Pena Edukasi
Mockup website modern di laptop dengan kartu artikel dan ikon mata yang menampilkan jumlah view

Tampilan jumlah kunjungan artikel pada website modern.

Membangun website modern dengan stack Next.js, Tailwind CSS, dan Cloudflare menjanjikan performa yang luar biasa cepat. Server component pada Next.js App Router memungkinkan halaman dirender di sisi server sehingga SEO menjadi sangat optimal. Namun, mimpi performa kilat ini bisa tiba-tiba hancur ketika kita mulai mengintegrasikan API pihak ketiga langsung ke dalam komponen server.

Salah satu kasus paling umum—dan mematikan bagi performa—adalah pemasangan fitur View Counter (penghitung jumlah tayangan artikel) yang memanggil data langsung dari Google Analytics 4 (GA4) API di halaman Home Grid.

Artikel ini akan membahas secara mendalam mengapa pemanggilan API di dalam grid artikel bisa membuat loading website menjadi sangat lambat (lelet), dan bagaimana kita menyelesaikan masalah ini secara elegan menggunakan arsitektur Client-Side Fetching dengan SWR.

Akar Masalah: "N+1 API Fetching" di Server Components

Bayangkan Anda memiliki sebuah halaman utama (homepage) yang menampilkan 20 artikel dalam berbagai desain grid bergaya bento box, majalah, atau timeline.

Untuk menampilkan jumlah tayangan (views) secara real-time, developer sering kali memanggil fungsi fetch ke Google Analytics API di dalam perulangan data artikel. Di Next.js Server Components, kodenya mungkin terlihat seperti ini:

// CONTOH KODE BURUK (Menyebabkan Loading Lambat)
const allArticles = await Promise.all(
  allArticlesRaw.map(async (article) => {
    // Memanggil API Google Analytics untuk SETIAP artikel
    const views = await getPageViews(`/post/${article.slug}`) 
    return { ...article, views }
  })
)

Mengapa ini menjadi bencana performa?

Kode di atas berjalan di backend (server). Next.js akan menahan (block) seluruh proses rendering halaman utama sampai Google mengembalikan jawaban untuk semua 20 artikel tersebut. Jika satu panggilan ke Google API membutuhkan waktu 200ms, maka 20 panggilan paralel bisa menciptakan bottleneck memori, memicu batas kuota API, dan membuat layar pengunjung putih kosong (blank) selama beberapa detik.

Kecepatan loading yang asalnya instan lenyap seketika, mengorbankan kenyamanan pengunjung (UX) dan metrik Core Web Vitals untuk SEO.

Konsep Solusi: Pola Asinkronus (Skeleton & Background Fetching)

Solusi paling efektif tanpa mengorbankan fitur view counter dan tanpa merusak tata letak CSS yang sudah ada adalah mengubah strategi fetching dari Server-Side menjadi Client-Side khusus untuk komponen angka kecil tersebut.

Alurnya adalah sebagai berikut:

  1. Server (Render Instan): Server Next.js hanya bertugas mengambil data kerangka artikel dari database lokal (Judul, Kategori, Gambar, Tanggal). Halaman dikirim ke browser pengunjung saat itu juga. Halaman langsung tampil!
  2. Client (Background Fetch): Di saat halaman sudah tampil dan pengunjung mulai membaca judul, sebuah komponen kecil (ikon mata) di sudut artikel memunculkan animasi loading ringan (...). Di belakang layar, ia menanyakan data tayangan ke server.
  3. Pembaruan UI: Beberapa milidetik kemudian, angka view muncul dengan mulus.

Mari kita masuk ke langkah-langkah implementasinya menggunakan SWR, library data fetching buatan Vercel yang sangat optimal untuk Next.js.

Baca Juga: Adab kepada Orang Tua dan Guru: Dua Pintu Keberkahan dalam Hidup

🚀 Lihat Demo Langsung (Live Demo)

Seluruh arsitektur Client-Side Fetching menggunakan SWR untuk Google Analytics API ini telah diterapkan dan terbukti sukses berjalan di portal Pena Edukasi. Anda dapat merasakan langsung bagaimana halaman home grid merender seketika, disusul dengan angka view yang muncul dengan mulus di latar belakang dengan mengunjungi situs berikut:

Kunjungi web.penaeducasi.com →

Step-by-Step Implementasi

Baca Juga: Cara Generate dan Verifikasi API Key IndexNow di Bing Webmaster Tools

Langkah 1: Buat API Route Terpusat (Endpoint)

Alih-alih membiarkan setiap kartu komponen menembak API Google secara mandiri, kita buat satu jembatan (API Route) di backend Next.js. File ini bertugas menerima permintaan dari browser dan meneruskannya ke Google dengan aman.

Buat file di app/api/views/route.ts:

import { NextResponse } from 'next/server';
import { getPageViews } from '@/lib/google-analytics'; // Fungsi koneksi GA4 Anda

// Memastikan API berjalan di Edge Runtime yang super ringan
export const runtime = 'edge';
export const dynamic = 'force-dynamic'; 

export async function GET(request: Request) {
  try {
    const { searchParams } = new URL(request.url);
    const slug = searchParams.get('slug');

    // Kembalikan 0 jika slug tidak valid
    if (!slug) return NextResponse.json({ views: 0 });

    // Tarik data dari Google Analytics 4
    const views = await getPageViews(slug);
    
    return NextResponse.json({ views });
  } catch (err) {
    // Graceful degradation: jangan buat web crash jika API Google tumbang
    console.error("Error API views:", err);
    return NextResponse.json({ views: 0 });
  }
}
Catatan Keamanan: Dengan cara ini, Private Key Google Anda tetap rahasia di server dan tidak bocor ke browser pengguna.

Langkah 2: Instalasi SWR

Buka terminal dan pasang library SWR. Ini akan menangani caching, rekoneksi otomatis, dan pembaruan data secara real-time.

npm install swr

Langkah 3: Buat Komponen Klien Dinamis (DynamicViewCount)

Buat komponen kecil khusus untuk menangani angka dan ikon. Komponen ini wajib menggunakan arahan 'use client' agar dieksekusi di browser.

Buat atau sisipkan kode ini di file komponen Anda (misalnya components/dynamic-view-count.tsx atau langsung di dalam file grid Anda):

'use client'

import useSWR from "swr"

// Fungsi fetch standar untuk SWR
const fetcher = (url: string) => fetch(url).then((res) => res.json())

// Fungsi pemformatan angka (misal: 1500 menjadi 1.5K)
function formatViews(num: number): string {
  if (num >= 1000000) return (num / 1000000).toFixed(1).replace(/\.0$/, '') + 'M'
  if (num >= 1000) return (num / 1000).toFixed(1).replace(/\.0$/, '') + 'K'
  return num.toString()
}

export function DynamicViewCount({ slug }: { slug: string }) {
  // Panggil endpoint API Route kita
  const { data, error } = useSWR(`/api/views?slug=${slug}`, fetcher)
  const isLoading = !data && !error
  
  // Tangani error dengan elegan
  if (error) return <>0</>
  
  // Tampilkan efek pulse (berkedip) ringan saat memuat di latar belakang
  if (isLoading) return <span className="animate-pulse">...</span>
  
  // Tampilkan hasil akhir
  return <>{formatViews(data.views || 0)}</>
}

Baca Juga: Cara Otomatisasi IndexNow Bing di Next.js dan Cloudflare Pages CMS

Langkah 4: Bersihkan Komponen Server (Hapus Blocking)

Sekarang, kembali ke file halaman utama (contoh: app/page.tsx). Hapus semua pemanggilan API Google Analytics dari fungsi utama. Biarkan komponen server ini seringan mungkin.

export default async function Home() {
  // 1. Ambil data artikel TANPA menunggu data views dari Google Analytics
  const allArticles = await getPublishedArticles() || []

  // ... logika filter kategori ...

  return (
    <main>
      {/* Kirim data artikel mentah (views kosong) ke komponen grid */}
      <BentoBoxGrid articles={pendidikan} />
    </main>
  )
}

Lalu, di dalam komponen grid Anda (misalnya home-grids.tsx), panggil komponen <DynamicViewCount/> yang sudah kita buat pada Langkah 3.

import { Eye } from "lucide-react"
import { DynamicViewCount } from "./dynamic-view-count"

// ... struktur kode lainnya ...

{/* Bagian ikon mata di dalam desain UI Anda */}
<div className="flex items-center gap-1.5 bg-black/50 text-white px-2.5 py-1 rounded-md text-xs">
   <Eye className="w-3.5 h-3.5 text-gray-300" />
   <span>
      {/* Injeksi komponen klien dengan mengirimkan spesifik slug */}
      <DynamicViewCount slug={`/post/${article.slug}`} />
   </span>
</div>

Hasil Akhir dan Manfaat

Dengan memisahkan beban kerja antara Server (untuk SEO dan kerangka UI) dan Client (untuk data dinamis sekunder seperti jumlah view), kita mendapatkan keseimbangan sistem yang sempurna.

  • Performa Memukau (Zero Blocking): Pengunjung tidak lagi harus menatap layar putih kosong. Gambar, judul, dan struktur CSS Tailwind dimuat seketika tanpa halangan.
  • UI Tetap Aman 100%: Karena kita hanya menukar teks angka dengan komponen <DynamicViewCount/>, seluruh hirarki CSS (padding, margin, absolute positioning) sama sekali tidak terganggu.
  • Data Tetap Akurat dan Real-time: SWR memiliki fitur pembaruan mandiri (focus revalidation). Jika pengguna berpindah tab lalu kembali lagi, SWR diam-diam mengecek apakah ada peningkatan penayangan dan memperbarui angkanya di layar tanpa harus me-refresh halaman!
  • Lebih Aman dari Limit API: Next.js Route Cache dan jaringan Edge network (seperti Cloudflare) bisa membantu mendinginkan arus lalu lintas yang masuk agar tidak langsung membakar kuota Google Analytics Data API secara berlebihan.

Menghadapi masalah loading akibat API eksternal tidak selalu berarti harus menurunkan kualitas desain fitur. Dengan memahami pola arsitektur Client-Side Fetching di era App Router modern, setiap developer dapat membangun web kaya fitur tanpa harus mengorbankan rasio kecepatan situs satu milidetik pun.

Artikel Terkait