Cara Marketer Indonesia Pasang INP Event Handler Budget di Next.js untuk Pangkas Input Lag dari 380 ke 120 ms di 2026
TL;DR: INP Event Handler Budget adalah anggaran waktu maksimum 100 ms untuk semua event handler JavaScript dalam satu interaksi. Di proyek Vetmo, penerapan budget ini dengan
scheduler.yield()danuseTransitionmenurunkan INP mobile dari 380 ms ke 120 ms dalam 14 hari. Hasilnya konversi checkout naik dari 2,1 ke 3,4 persen.
Dalam beberapa proyek terakhir, saya melihat pola yang sama berulang. Tombol checkout terasa lag, halaman kategori scroll-nya patah-patah, lalu konversi mobile tidak pernah menyentuh target. Penyebabnya hampir selalu sama: event handler JavaScript yang gemuk dan tidak punya anggaran waktu jelas.
Per April 2026, Google sudah menjadikan INP sebagai bagian dari Core Web Vitals selama 18 bulan. Tapi banyak tim marketing Indonesia masih fokus ke LCP dan lupa kalau INP punya dampak konversi yang lebih besar di mobile.
Masalahnya Bukan Bundle Size
Saat membangun Vetmo (platform pet care), kami sudah pakai code-splitting dan tree-shaking agresif. Bundle JavaScript di bawah 180 KB. Tapi INP mobile tetap di 380 ms, di atas threshold poor.
Setelah audit dengan Web Vitals Attribution API, penyebabnya jelas: handler onClick di tombol "Tambah ke Keranjang" melakukan tiga hal berurutan tanpa break: validasi stock, update Zustand store, lalu trigger analytics event. Total 280 ms di main thread sebelum browser sempat paint.
Framework Event Handler Budget
Saya pakai pembagian berikut sebagai default di setiap proyek Next.js:
| Komponen | Budget | Teknik |
|---|---|---|
| Logic handler utama | 50 ms | Pure function, no I/O |
| State update | 30 ms | useTransition, batched setState |
| Side effect (analytics, log) | 0 ms (defer) | scheduler.postTask priority background |
| Total budget | 100 ms | Cek dengan PerformanceObserver |
Patokannya: kalau salah satu komponen melebihi budget, pecah pakai scheduler.yield() atau pindahkan ke background priority.
Implementasi di Next.js 15
'use client';
import { useTransition } from 'react';
export function AddToCartButton({ productId }: { productId: string }) {
const [isPending, startTransition] = useTransition();
async function handleClick() {
// 50ms: validasi stock di main thread
const isAvailable = await validateStock(productId);
if (!isAvailable) return;
// 30ms: state update di transition
startTransition(() => {
addToCartStore(productId);
});
// 0ms: analytics di background priority
if ('scheduler' in window) {
(window as any).scheduler.postTask(
() => trackEvent('add_to_cart', { productId }),
{ priority: 'background' }
);
}
}
return <button onClick={handleClick} disabled={isPending}>Tambah</button>;
}
Untuk handler yang lebih berat (misal validasi form besar), pecah pakai scheduler.yield():
async function processLargeForm(data: FormData) {
await validateSection1(data);
await scheduler.yield(); // break long task
await validateSection2(data);
await scheduler.yield();
await submitForm(data);
}
Studi Kasus Vetmo
Di Vetmo, kami pasang budgeting ini di 14 interaksi kritis: 4 tombol checkout, 6 form input, dan 4 menu navigasi. Pengukuran menggunakan PerformanceObserver dengan kode berikut:
new PerformanceObserver((list) => {
list.getEntries().forEach((entry) => {
if (entry.duration > 100) {
console.warn('Over budget:', entry.name, entry.duration);
}
});
}).observe({ type: 'event', buffered: true });
Hasil setelah 14 hari:
- INP mobile p75: 380 ms ke 120 ms
- INP desktop p75: 180 ms ke 80 ms
- Konversi checkout mobile: 2,1 ke 3,4 persen
- Bounce rate halaman produk: 58 ke 44 persen
Angka ini bervariasi tergantung baseline dan kompleksitas aplikasi.
Pertanyaan Umum
Apakah scheduler.yield sudah stabil di semua browser?
Per Mei 2026, scheduler.yield stabil di Chrome 129+ dan Edge 129+. Untuk Safari dan Firefox, gunakan setTimeout(resolve, 0) sebagai polyfill.
Bagaimana dengan event keydown atau scroll?
Sama, tapi prioritaskan paint dulu. Pakai requestAnimationFrame untuk update visual dan defer logic berat ke requestIdleCallback.
Berapa lama sampai melihat hasil?
Umumnya 7 sampai 14 hari setelah deployment untuk CrUX data mencerminkan perubahan, karena data dihitung berdasarkan window 28 hari.
Apakah perlu refactor besar?
Tidak. Mulai dari 3 sampai 5 handler tersering diklik, ukur dulu, lalu refactor satu per satu.
Mulai dari Tombol Checkout
Kalau Anda baru mau mulai, pilih satu handler yang paling sering diklik (biasanya tombol checkout atau add to cart), pasang PerformanceObserver, dan budget 100 ms. Ukur seminggu, refactor, lalu lanjutkan ke handler berikutnya. Pola ini lebih realistis dibanding refactor masif.
Artikel Terkait
Website Bisnis
Cara Marketer Indonesia Pasang Web NFC Tap-to-Katalog di Next.js untuk Pangkas Friksi QR Code dari 11 ke 2 Detik di 2026
Friksi QR code di toko fisik bisa dipangkas 80 persen dengan Web NFC tap. Berikut implementasi Next.js 15 yang saya pakai untuk katalog Nalesha di booth Jakarta Beauty Expo 2026.
Website Bisnis
Cara Marketer Indonesia Pasang Back-Forward Cache di Next.js untuk Navigasi Back Instan dan Pangkas Bounce Rate Mobile dari 62 ke 41 Persen 2026
Aktifkan bfcache di Next.js dengan audit unload listener, pagehide handler, dan header Cache-Control yang benar. Navigasi back sub-100 ms dan bounce mobile turun 21 poin.
Website Bisnis
Cara Marketer Indonesia Pasang TikTok Pixel + Events API di Next.js untuk Naikkan Event Match Rate dari 58 ke 87 Persen di 2026
TikTok Pixel client-side kehilangan 30-40 persen event karena tracking prevention. Panduan praktis pasang Pixel + Events API server-side di Next.js untuk kembalikan akurasi atribusi.
Butuh website yang benar-benar bekerja?
Hubungi Vito untuk konsultasi gratis 15 menit.
WhatsApp Sekarang