Skip to content
Konsultasi

Migrasi Frontend ke Vercel: Next.js Standalone + Docker

Catatan migrasi frontend blog ini ke Vercel: output standalone Next.js, Dockerfile multi-stage untuk image ramping, dan preview deployment otomatis per branch.

Adityo Guni Waluyo4 menit baca

Mengapa Frontend Dipindah ke Vercel

Blog ini awalnya jalan sebagai satu container monolitik: frontend Next.js dan API Python dikemas bersama, dibangun sekali, dijalankan bersama. Pola itu praktis di awal, tapi cepat menemui batasnya. Setiap perubahan kecil di sisi frontend — ganti komponen, update artikel — memaksa image seluruh stack dibangun ulang, dan rollback jadi operasi all-or-nothing.

Komit repo pribadi pekan lalu menunjukkan arah baru: frontend dipecah jadi container image terpisah, lalu bermigrasi ke Vercel dengan model branch main/staging/api. Artikel ini bedah langkah migrasinya — kenapa output: 'standalone' jadi kunci, bagaimana multi-stage build Docker menjaga image tetap ramping, dan bagaimana model branch di Vercel menggantikan ritual deploy manual.

output: 'standalone' — Fondasi Deployment Minimal

Sejak Next.js 12, framework ini punya fitur output file tracing: saat next build berjalan, dependency tiap halaman dianalisis statis lewat @vercel/nftimport, require, sampai pemakaian fs — untuk menentukan file mana saja yang benar-benar dibutuhkan runtime produksi. Hasilnya, deployment tidak lagi butuh folder node_modules utuh.

Aktifkan mode ini satu baris di next.config.js:

module.exports = {
  output: 'standalone',
}

Setelah build, muncul folder .next/standalone berisi file minimal produksi plus server.js yang bisa dijalankan tanpa next start. Dua folder yang sengaja tidak ikut disalin otomatis adalah public dan .next/static — keduanya idealnya dilayani CDN — tapi bisa dimasukkan manual:

cp -r public .next/standalone/ && cp -r .next/static .next/standalone/.next/
node .next/standalone/server.js

Pola inilah yang dipakai saat memecah frontend jadi image terpisah: builder menjalankan next build, runner hanya menyalin hasil standalone. Node_modules dev-dependency, source map, dan toolchain build tidak pernah ikut ke image final — ukuran turun drastis dan permukaan serangan menyusut.

Multi-Stage Build: Builder Terpisah dari Runner

Multi-stage build adalah idiom Docker untuk kasus ini: beberapa instruksi FROM dalam satu Dockerfile, tiap stage punya basis berbeda, dan artefak disalin selektif antar stage. Semua yang tidak dibutuhkan runtime — compiler, build tool, dependency sementara — tertinggal di stage builder, tidak masuk image final.

FROM node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:22-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/static ./.next/static
CMD ["node", "server.js"]

Dua catatan dari best practice resmi docker-node yang relevan di sini. Pertama, jalankan proses dengan NODE_ENV=production — ini juga jalur masuk konfigurasi runtime seperti API key. Kedua, Node.js tidak dirancang jadi PID 1; beri --init saat docker run atau pakai init wrapper seperti tini/dumb-init supaya sinyal SIGTERM benar-benar sampai ke proses. Alternatifnya: bypass package.json start script dan panggil langsung CMD ["node", "server.js"] — exit signal tidak ditelan npm. Image node resmi juga menyediakan user node (uid 1000) bila ingin container jalan non-root.

Model Branch main/staging/api di Vercel

Setelah image terpisah, langkah berikutnya memindahkan hosting frontend ke Vercel. Model yang dipilih: main untuk production, staging dan api sebagai branch kerja. Setiap push ke branch terhubung memicu deployment — main jadi deployment production, branch lain jadi preview dengan URL unik.

Dua fitur Vercel yang membuat model ini nyaman. Monorepo support di Vercel memungkinkan beberapa project dalam satu repositori, dengan Root Directory per project; commit yang tidak menyentuh direktori frontend otomatis di-skip sehingga build queue tidak menumpuk. Sementara Build Settings — framework preset, build command, output directory, Node.js version — bisa di-override per project atau per deployment lewat vercel.json. Kombinasi keduanya membuat pipeline per branch tetap terkontrol tanpa konfigurasi CI eksternal.

Apa yang Terjadi pada Image Docker Lama

Migrasi ke Vercel bukan berarti Dockerfile jadi sia-sia. Path standalone tetap dipakai untuk build lokal dan environment staging sendiri; perbedaannya kini hanya soal siapa yang menjalankan server.js — container sendiri atau platform. Pemisahan frontend ke container sendiri juga menyisakan pelajaran arsitektural: next build menghasilkan artefak yang secara desain sudah portabel, jadi keputusan hosting jadi keputusan yang murah untuk diubah. Untuk stack yang masih memakai syntax highlighting Shiki, perbandingan detailnya ada di tulisan sebelumnya tentang Shiki vs Prism.js.

Penutup

Inti migrasi ini tiga lapis: output: 'standalone' membuat artefak Next.js minimal dan portabel, multi-stage build memastikan image yang dijalankan hanya berisi runtime produksi, dan model branch Vercel menggantikan deploy manual dengan preview otomatis. Stack blog ini sekarang: frontend Next.js di Vercel, API tetap di belakang, konten tetap ditulis dan diverifikasi dari sumber terbuka — seperti artikel tentang embed YouTube, Mermaid, dan Recharts yang memakai token serupa. Untuk detail teknis, langsung ke dokumentasi output Next.js dan panduan multi-stage build Docker.