Nextjs Middleware Edge Runtime Image Optimization Redirect Rewrites
Definisi
Halaman ini membahas empat bagian yang sering muncul di Next.js production app:
- Middleware: logika yang berjalan sebelum request masuk ke route/page tujuan.
- Edge Runtime: runtime yang ringan dan dekat ke user, dengan batasan berbeda dari Node.js runtime.
- Image Optimization: mekanisme Next.js untuk mengoptimalkan gambar lewat
next/imagedan image optimizer bawaan. - Redirects dan rewrites: aturan routing di level Next.js atau server yang mengubah tujuan request tanpa selalu mengubah URL yang dilihat user.
Empat topik ini sering dipakai bersama, tapi fungsinya berbeda. Kalau dicampur, gejalanya biasanya baru kelihatan saat production: redirect loop, request yang salah tujuan, gambar lambat, atau middleware yang terlalu mahal.
Kapan middleware dipakai
Middleware dipakai kalau kamu perlu memutuskan sesuatu sebelum request mencapai halaman, route handler, atau file statis tertentu.
Contoh penggunaan yang memang masuk akal:
- autentikasi ringan: cek ada session cookie atau tidak
- redirect user yang belum login ke halaman login
- rewrite request berdasarkan locale, subdomain, atau tenant
- menolak request awal berdasarkan header, path, atau IP sederhana
- menambahkan atau memodifikasi header response
- edge personalization yang sangat ringan
- observasi request awal, misalnya untuk logging terbatas atau tracing
Middleware cocok untuk routing decision, bukan untuk kerja berat.
Kapan tidak perlu middleware
Jangan pakai middleware kalau:
- logika itu hanya dibutuhkan di satu page atau satu route handler
- kamu butuh akses database, query kompleks, atau library Node.js yang berat
- keputusan bisa dibuat di Server Component, route handler, atau server action
- kamu hanya ingin validasi form biasa
- kamu bisa menyelesaikannya dengan redirect statis di konfigurasi build/deploy
Aturan praktisnya:
- masih bisa ditunda sampai route/page → jangan middleware
- harus diputuskan sebelum route jalan → middleware layak dipakai
Ciri middleware yang sehat
- singkat
- deterministik
- tidak bergantung pada proses mahal
- tidak mengubah banyak hal sekaligus
- hanya mencakup path yang benar-benar perlu
Kalau middleware mulai terasa seperti mini backend, biasanya desainnya sudah kebablasan.
Cara kerja middleware di Next.js
Middleware dieksekusi lebih awal daripada rendering page. Alurnya kira-kira begini:
Perbedaan keputusan di middleware penting:
- redirect: browser diarahkan ke URL baru, URL di address bar berubah
- rewrite: request dialihkan secara internal, URL di address bar tetap
- next / lanjut: request diteruskan ke target normal
Edge Runtime vs Node.js runtime
Middleware di Next.js berjalan di Edge Runtime, bukan Node.js runtime biasa. Ini sering disalahpahami karena kelihatannya sama-sama “server-side”. Padahal batas kemampuannya berbeda.
Edge Runtime
Edge Runtime dirancang untuk eksekusi cepat di jaringan yang dekat ke user. Fokusnya:
- cold start kecil
- cocok untuk keputusan ringan per request
- latency rendah untuk operasi sederhana
Batas yang perlu diingat:
- tidak semua API Node.js tersedia
- library yang bergantung pada filesystem, native module, atau proses Node penuh bisa gagal
- kerja berat seperti query DB kompleks atau transform data besar bukan target utamanya
Node.js runtime
Node.js runtime adalah runtime server penuh yang biasa dipakai untuk:
- Server Component
- Route Handler tertentu
- server action
- proses yang butuh akses Node API lengkap
Ciri utamanya:
- lebih fleksibel
- bisa memakai banyak library ekosistem Node
- lebih cocok untuk kerja backend yang sebenarnya
Ringkas perbedaannya
- Edge Runtime: cepat, ringan, dekat ke user, tetapi terbatas
- Node.js runtime: lebih lengkap, lebih bebas, tetapi umumnya lebih berat
Kalau kamu butuh akses database atau utilitas Node yang kompleks, pindahkan logika ke server route/handler, jangan dipaksa di middleware.
Catatan implementasi middleware
Contoh sederhana:
import { NextResponse, type NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
const isLoggedIn = request.cookies.has('session')
if (!isLoggedIn && request.nextUrl.pathname.startsWith('/dashboard')) {
const loginUrl = new URL('/login', request.url)
loginUrl.searchParams.set('from', request.nextUrl.pathname)
return NextResponse.redirect(loginUrl)
}
return NextResponse.next()
}
export const config = {
matcher: ['/dashboard/:path*'],
}Hal yang perlu diperhatikan:
- pakai
matchersupaya middleware tidak jalan ke semua request tanpa alasan - batasi path yang dicek supaya biaya per request tetap rendah
- kalau ada redirect, pastikan targetnya tidak memicu middleware yang sama secara berulang
- kalau menulis cookie atau header, cek efeknya di response akhir
Image Optimization di Next.js
Image optimization di Next.js biasanya mengacu pada penggunaan next/image, yang membantu browser menerima gambar dengan ukuran dan format yang lebih efisien.
Tujuannya bukan sekadar “memperkecil file”, tapi membuat delivery gambar lebih cocok untuk konteks render halaman.
Apa yang dilakukan Next.js
Saat kamu memakai komponen Image, Next.js bisa membantu dengan:
- menyesuaikan ukuran gambar sesuai kebutuhan layout
- menghasilkan versi yang lebih kecil untuk viewport tertentu
- mengoptimalkan format gambar bila didukung browser dan lingkungan
- menunda pemuatan gambar di bawah fold lewat lazy loading
- mencegah layout shift dengan menyediakan dimensi yang jelas
Alur sederhananya
Cara kerjanya di production
Ada beberapa pola yang umum:
- gambar lokal: Next.js bisa memproses asset yang tersedia di aplikasi
- gambar remote: domain harus diizinkan, lalu optimizer mengambil dan memproses gambar itu
- cache layer: hasil optimasi biasanya dicache supaya request berikutnya lebih murah
Jadi, optimasi gambar itu bukan sekadar transform sekali lalu selesai. Di production, responsnya sangat dipengaruhi cache, ukuran viewport, dan format yang diminta browser.
Hal yang sering kelihatan di debugging
- gambar terasa lambat karena ukuran asli terlalu besar
- layout bergeser karena dimensi tidak diset dengan benar
- remote image gagal tampil karena domain belum diizinkan
- gambar tampak bagus di local, tapi lambat di production karena cache belum terisi atau ukuran source terlalu besar
Praktik yang sehat
- selalu set
widthdanheightatau gunakan layout yang setara - gunakan
sizeskalau gambar responsif - jangan pakai gambar resolusi besar tanpa alasan
- pastikan domain remote memang terpercaya dan dikonfigurasi
- cek apakah kompresi berlebihan membuat kualitas turun
Jebakan umum image optimization
-
Mengira
next/imageotomatis menyelesaikan semua masalah performaTidak. Kalau source image-nya sudah sangat besar atau salah dimensi, optimizer hanya mengurangi sebagian masalah.
-
Lupa mengatur dimensi
Ini sering memicu layout shift dan hasil render yang tidak stabil.
-
Remote image tidak masuk whitelist
Di production, gambar bisa gagal karena host sumber belum diizinkan.
-
Menggunakan gambar yang terlalu besar untuk konteks kecil
Misalnya avatar 3000px untuk elemen 48px. Itu pemborosan bandwidth.
-
Mengira cache selalu langsung hangat
Request pertama bisa lebih mahal dibanding request berikutnya.
Redirects dan rewrites
Redirects dan rewrites sama-sama mengubah alur request, tapi hasil akhirnya berbeda.
Redirect
Redirect memindahkan user ke URL lain secara eksplisit. Browser akan melihat URL baru.
Kapan dipakai:
- pindah struktur URL lama ke baru
- canonicalisasi URL
- login flow
- pemindahan halaman permanen atau sementara
- migrasi rute
Contoh perilaku:
/old→/new- browser menampilkan
/new
Rewrite
Rewrite mengalihkan request secara internal tanpa mengubah URL di browser.
Kapan dipakai:
- proxy ke backend atau service lain
- menjaga URL publik tetap stabil
- multi-tenant atau locale mapping
- memetakan rute publik ke lokasi internal
Contoh perilaku:
/blog/123tetap terlihat di browser- tapi request internal bisa dilayani oleh target lain
Bedanya secara praktis
- redirect mengubah apa yang user lihat
- rewrite mengubah apa yang server layani
Kalau tujuanmu adalah migrasi URL, pakai redirect. Kalau tujuanmu adalah menyembunyikan perubahan internal, pakai rewrite.
Jebakan umum redirects dan rewrites
1. Redirect loop
Ini terjadi kalau aturan redirect mengarah ke URL yang masih cocok dengan aturan yang sama.
Contoh klasik:
- middleware redirect semua request ke
/login - tetapi
/loginjuga ikut kena middleware
Hasilnya: loop.
Solusi:
- exclude path target dari matcher
- tambahkan guard sebelum redirect
- pastikan target final tidak memicu rule yang sama
2. Salah pilih redirect vs rewrite
Kalau kamu butuh URL browser berubah, tapi memakai rewrite, user tetap melihat URL lama.
Kalau kamu butuh URL tetap sama, tapi memakai redirect, browser berpindah halaman dan bisa menambah round-trip.
3. Konflik dengan route statis
Rule rewrite/redirect yang terlalu umum bisa menimpa route yang sebenarnya valid.
Solusi:
- prioritaskan rule yang paling spesifik
- cek urutan aturan
- uji path yang mirip tapi bukan target
4. Mengabaikan trailing slash, base path, dan locale
Di production, detail kecil seperti ini bisa mengubah hasil match.
Contoh gejala:
- rule jalan di local, gagal di production
- path yang sama diproses berbeda karena locale prefix
- redirect dianggap tidak cocok karena trailing slash berbeda
5. Mencampur middleware dengan redirect statis tanpa rencana
Kalau satu masalah bisa selesai di konfigurasi statis, itu biasanya lebih sederhana daripada logic runtime.
Gunakan middleware hanya kalau keputusan memang perlu dinamis per request.
6. Rewrite ke target yang tidak siap
Rewrite yang terlihat benar bisa menghasilkan 404 atau response aneh kalau target internalnya tidak valid.
Debugging yang berguna:
- cek path asli
- cek path target internal
- cek apakah target route benar-benar ada
- bandingkan hasil di local dan production
Contoh alur gabungan
Kalau digabung, alurnya biasanya seperti ini:
- request masuk ke Next.js
- middleware memeriksa cookie, header, atau path
- middleware memutuskan redirect, rewrite, atau lanjut
- jika lanjut, route/page menghasilkan response
- response bisa memuat image optimization atau resource lain
- browser menerima hasil akhir
Diagram berikut merangkum alurnya:
Catatan debugging produksi
Kalau masalahnya muncul hanya di production, cek urutan ini:
- apakah middleware match terlalu luas
- apakah response redirect/rewrite sesuai target
- apakah ada loop antar-rute
- apakah image domain dan ukuran sudah benar
- apakah runtime yang dipakai memang Edge atau Node
- apakah cache membuat hasil lama masih terlihat
Biasanya akar masalahnya bukan satu bug besar, tapi kombinasi rule yang terlalu umum, assumption runtime yang salah, dan cache yang menutupi perubahan.
Referensi terkait
- Next.js Middleware: untuk kontrol request awal dan decision per request
- Edge Runtime: untuk memahami batasan API dan library yang bisa dipakai
next/image: untuk optimasi gambar responsif dan caching- Redirects/Rewrites: untuk migrasi URL, proxy internal, dan routing yang tidak terlihat oleh user
Kalau kamu sedang debug production, fokus paling cepat biasanya: matcher middleware, target rewrite/redirect, dan domain image yang diizinkan. Tiga itu sering jadi sumber masalah yang kelihatan “acak” padahal polanya konsisten.