Next.js Lambat Setelah Update 13.4. Ini Trik Aku Ngerapihin Bundle Size Biar Ngebut Lagi
Halo guys! Siapa di sini yang developer Next.js, mungkin sudah pakai versi 13 atau bahkan 14, tapi tiba-tiba merasa deployment jadi lebih lama, loading awal aplikasi di browser kok agak seret, dan bundle size membengkak tanpa alasan yang jelas?
Kalau kamu mengalami ini, tenang saja. Kamu tidak sendirian.
Next.js adalah framework yang luar biasa. Perpindahan ke App Router di versi 13.4 memang membawa banyak perubahan fundamental, terutama soal bagaimana bundling bekerja antara Server Components dan Client Components. Di satu sisi, App Router menawarkan performa yang lebih baik di sisi server dan UX yang lebih mulus berkat Server Components dan streaming. Namun, kalau kita tidak disiplin dalam penulisan kodenya, App Router justru bisa menjadi bumerang yang membuat bundle kita jadi gajah bengkak.
Di Javapixa Creative Studio, kami sering banget menghadapi kasus di mana klien datang dengan aplikasi Next.js yang tadinya ngebut di versi 12, tapi setelah migrasi atau upgrade ke 13.4 ke atas, performanya menurun drastis. Biasanya, masalah utamanya hanya satu: mismanagement terhadap bundle size.
Aku akan spill trik-trik yang biasa aku pakai buat "bersih-bersih" dan merapikan bundle size di Next.js 13.4+ hingga aplikasi kita kembali ngebut seperti sedia kala. Ini bukan cuma soal config dasar, tapi trik yang benar-benar fokus pada pemanfaatan App Router secara maksimal.
---
1. Kenali Musuh: Analisis Bundle Sebelum Bertindak
Prinsip pertama dalam optimasi adalah: jangan tebak-tebak buah manggis. Kita harus tahu persis siapa package atau komponen yang paling banyak menyumbang berat.
Sebelum kamu panik dan mengubah kode di sana-sini, langkah wajib yang harus kamu lakukan adalah memasang Next Bundle Analyzer.
bash
Instal dulu paketnya
npm install --save-dev @next/bundle-analyzerAtau pakai yarn/pnpm
pnpm install -D @next/bundle-analyzerSetelah terinstal, kamu perlu sedikit memodifikasi next.config.js agar analyzer berjalan saat proses build.
Dengan analyzer ini, kamu akan disajikan visualisasi interaktif berupa treemap yang menunjukkan setiap chunk dalam bundle produksi. Ini adalah insight paling berharga karena kamu bisa melihat:
- Dependencies Duplikat: Sering terjadi kalau kita pakai dua versi library yang sama.
- Library Gajah: Library pihak ketiga mana yang ukurannya jauh lebih besar dari yang kamu duga (misalnya, kamu hanya butuh satu fungsi tapi mengimpor seluruh package).
- Client Component Bloat: Komponen mana yang paling besar yang terpaksa di-bundle di sisi klien (biasanya komponen yang seharusnya bisa di-lazy load).
Setelah kamu tahu nama-nama paket besar yang bikin berat, baru kita masuk ke tahap eksekusi.
2. Disiplin Ketat pada 'use client'
Ini adalah fondasi App Router. Server Components (SC) adalah default di Next.js 13/14. SC tidak ikut di-bundle ke browser, artinya ukurannya nol di sisi klien. Client Components (CC) adalah kebalikannya.
Masalah performa muncul ketika kita secara tidak sengaja "menularkan" CC ke SC, atau lebih parah, menjadikan satu halaman besar sebagai CC padahal hanya 5% bagiannya yang butuh interaksi.
A. Isolasi Komponen Interaktif
Jangan pernah menempatkan direktif 'use client' di komponen paling atas (seperti di layout atau halaman utama) hanya karena kamu butuh state di salah satu bagian kecil.
Contoh Kasus Gagal (Bundle Berat):
jsx
// components/HeavyPage.jsx
'use client'; // <-- Seluruh komponen dan semua import-nya akan di-bundle ke clientimport { ChartLibrary } from 'huge-chart-library'; // Library besar ikut ke client
import { InputWithState } from './InputWithState';Solusi Profesional (Bundle Ringan):
Buat komponen wrapper sekecil mungkin yang membutuhkan state atau hooks, lalu beri tag 'use client' di sana. Biarkan komponen induk dan import library besar tetap menjadi Server Components.
jsx
// components/ClientChartWrapper.jsx
'use client';import { ChartLibrary } from 'huge-chart-library'; // Hanya ini yang di-bundle ke client
import { useState } from 'react';export default function ClientChartWrapper() {
// ... logic chart
return ;
}// app/dashboard/page.js (Server Component)
import ClientChartWrapper from '@/components/ClientChartWrapper';export default function DashboardPage({ initialData }) {
return (
Data Dashboard (Server Side Rendered)
{/ Hanya bagian ini yang di-bundle ke client /}
);
}Intinya: Pisahkan SC dan CC seperti air dan minyak.
B. Manfaatkan Props untuk Konten Statis
Kalau kamu punya sebuah Client Component (misalnya, tombol interaktif) yang harus merender children yang bersifat statis (teks, gambar, dll.), pastikan kamu passing children itu sebagai props dari Server Component.
Ketika Next.js melihat children tersebut datang dari SC, ia akan memastikan bahwa konten statis tersebut di-render di server dan hanya wrapper CC-nya saja yang di-hydrate di klien. Ini sangat ampuh mengurangi hydration overhead.
3. Dynamic Imports: Kunci Kecepatan Sejati
Ini mungkin trik paling tua dalam optimasi frontend, tapi sering dilupakan, dan di Next.js, ini sangat efektif berkat next/dynamic.
Kalau kamu punya komponen yang jarang digunakan, atau hanya digunakan setelah interaksi tertentu (misalnya modal, peta interaktif, editor teks WYSIWYG, atau chart yang baru muncul setelah tab diklik), wajib menggunakan dynamic import.
Dengan dynamic import, Next.js akan memecah kode komponen tersebut menjadi chunk terpisah, dan chunk itu baru akan di-download oleh browser saat komponen tersebut benar-benar dibutuhkan.
Bagaimana cara kerjanya?
Misalnya kamu pakai library editor teks seperti Draft.js atau TinyMCE yang ukurannya bisa mencapai ratusan KB.
Kode Bermasalah (Import biasa):
jsx
// app/editor/page.js (atau Client Component di dalamnya)
'use client';
import { TinyMCEEditor } from 'tinymce-react'; // Ini langsung masuk bundle utama
// ...Kode Ngebut (Dynamic Import):
jsx
// components/DynamicEditor.jsx
'use client';
import dynamic from 'next/dynamic';const TinyMCEEditor = dynamic(
() => import('tinymce-react').then(mod => mod.TinyMCEEditor),
{
// Opsi penting: Jangan render di server
ssr: false,
// Loading state saat komponen sedang di-download
loading: () => Memuat editor...
}
);Dengan ssr: false, kita memastikan bahwa library editor yang besar itu tidak pernah coba di-render di sisi server (yang bisa bikin build lama) dan hanya akan di-download di sisi klien saat komponen itu dipanggil.
4. Audit Dependency: Hati-Hati dengan Monster Lama
Setelah melakukan dynamic import pada komponen, fokus selanjutnya adalah pada package yang kamu impor di node_modules.
A. Specific Import vs. Full Library
Banyak developer yang masih terbiasa mengimpor seluruh package padahal hanya butuh satu atau dua fungsi. Ini sering terjadi pada utility libraries seperti Lodash, Ramda, atau bahkan icon libraries.
Contoh Boros:
javascript
// Mengimpor seluruh Lodash (ukurannya lumayan)
import _ from 'lodash';
const result = _.debounce(handleInput, 500);Contoh Hemat:
javascript
// Hanya mengimpor fungsi yang dibutuhkan (Tree Shaking jadi lebih efektif)
import debounce from 'lodash/debounce';
const result = debounce(handleInput, 500);Atau, kalau kamu menggunakan library modern, pastikan tree shaking sudah berjalan optimal.
B. Ganti Library Kuno yang Tidak Tree-Shakeable
Beberapa library pihak ketiga yang sudah lama tidak di-maintain mungkin tidak mendukung tree shaking secara penuh. Ini berarti, walaupun kamu hanya mengimpor satu fungsi, seluruh kode library tersebut tetap ikut masuk ke bundle.
Contoh klasik adalah Moment.js. Moment.js terkenal sangat besar karena membawa semua locale (bahasa) yang mungkin tidak kamu butuhkan.
Solusi: Ganti Moment.js dengan alternatif modern yang ukurannya jauh lebih kecil dan tree-shakeable seperti Date-fns atau Luxon. Perubahan ini saja bisa memangkas puluhan, bahkan ratusan KB dari bundle kamu.
C. Bersihkan Dead Code dan Unused Dependencies
Gunakan alat seperti depcheck untuk menemukan package di package.json yang sudah tidak kamu pakai tapi masih terinstal. Hapus saja. Setiap paket yang ada di node_modules memiliki potensi untuk di-bundle, bahkan jika tree shaking sudah berjalan.
5. Konfigurasi Next.js Tambahan untuk App Router
Sejak App Router, ada beberapa konfigurasi yang bisa kita optimalkan untuk memastikan build lebih ringan:
A. Mengoptimalkan Font dengan next/font
Kalau kamu masih mengimpor Google Fonts secara manual (lewat CSS atau link di _document.js atau layout.js), segera ganti ke next/font.
next/font secara otomatis mengoptimalkan font kamu, menghilangkan request eksternal ke Google, dan memastikan font di-self-host dan di-preload dengan benar. Hasilnya? Tidak hanya bundle size visual (CSS/Font) yang ramping, tapi juga peningkatan signifikan pada metrik CLS (Cumulative Layout Shift) dan LCP (Largest Contentful Paint).
B. Image Optimization (Selalu Wajib!)
Meskipun Next.js sudah punya next/image, banyak yang lupa mengkonfigurasi quality dan formatnya. Pastikan kamu selalu menentukan ukuran (width/height) dan menggunakan format modern seperti WebP atau AVIF jika memungkinkan. Next.js akan memproses gambar ini saat build, memastikan gambar yang disajikan adalah versi paling optimal.
C. Server Components & Data Fetching (Prevent Bundle Leak)
Salah satu keunggulan terbesar SC adalah data fetching yang cepat. Pastikan semua operasi I/O (akses database, panggilan API eksternal) terjadi di Server Components.
Kalau kamu melakukan data fetching di Client Component, kamu tidak hanya membebani klien dengan pekerjaan fetching, tetapi juga berpotensi menyeret library yang hanya dibutuhkan di sisi server (misalnya library klien database) ke bundle klien. Jaga agar Client Components hanya fokus pada interaktivitas, bukan manajemen data yang berat.
---
6. Penutup: Mengapa Optimasi Next.js Itu Investasi Krusial
Mengoptimalkan bundle size di Next.js 13.4 ke atas memang membutuhkan perhatian ekstra, terutama karena kompleksitas App Router. Tapi percayalah, upaya ini sangat setimpal. Aplikasi yang cepat bukan hanya masalah kenyamanan developer saat build, tetapi langsung berdampak pada:
- SEO: Kecepatan adalah faktor kunci peringkat Google (Core Web Vitals).
- Konversi: Pengguna cenderung meninggalkan situs yang lambat.
- Biaya: Bandwidth yang lebih rendah, khususnya untuk aplikasi besar.
Jika kamu merasa trik-trik di atas terlalu teknis atau kamu tidak punya waktu untuk melakukan audit mendalam pada aplikasi Next.js milikmu, jangan khawatir. Di Javapixa Creative Studio, kami memiliki tim expert yang berspesialisasi dalam performance engineering dan optimasi Next.js.
Kami bukan hanya membangun aplikasi dari nol, tapi juga membantu membersihkan, memigrasi, dan mempercepat aplikasi yang sudah ada, memastikan aplikasi Next.js kamu mencapai skor Core Web Vitals tertinggi dan memberikan pengalaman pengguna yang secepat kilat. Kami akan melakukan audit menyeluruh, merapikan use client, menerapkan dynamic import di tempat yang tepat, dan memastikan setiap chunk kode bekerja efisien.
Jangan biarkan performa aplikasi kamu menurun hanya karena salah bundling. Hubungi Javapixa Creative Studio sekarang, dan mari kita jadikan aplikasi Next.js kamu ngebut lagi!