Kenapa ini penting
Aplikasi yang hanya jalan di localhost:3000 belum bisa dinikmati siapa pun selain kamu. Deploy adalah proses memindahkan aplikasi ke server yang menyala 24 jam dan bisa diakses lewat internet dengan alamat seperti https://blogkamu.com. Di tahap ini banyak hal yang "berjalan baik di laptopku" tiba-tiba rusak: environment variable lupa diisi, database berupa file lokal hilang, atau fitur yang ternyata butuh server tidak didukung hosting statis.
Modul ini membahas pilihan deploy Next.js, kapan memakai yang mana, dan langkah lengkap mendeploy proyek full-stack ke Vercel dengan database Turso. Kamu juga akan belajar mode standalone untuk server sendiri (VPS atau Docker) dan kapan aplikasi bisa diekspor menjadi file statis murni.
Analogi: membangun aplikasi itu seperti memasak di dapur rumah. Deploy itu membuka warung: kamu butuh tempat (hosting), bahan yang tersedia di sana (env var, database), dan papan nama yang mudah ditemukan (domain). Resepnya sama, tapi persiapannya berbeda.
Konsep inti
Empat cara deploy Next.js
Dokumentasi Next.js 16 menyebut empat bentuk deploy:
| Cara | Dukungan fitur | Cocok untuk |
|---|---|---|
Node.js server (next build + next start) |
Semua fitur | VPS, server sendiri, platform yang menjalankan Node |
| Docker container | Semua fitur | Kubernetes, cloud yang menjalankan container |
Static export (output: 'export') |
Terbatas | Situs statis murni di hosting file (GitHub Pages, S3, CF Pages statis) |
| Adapter platform | Bergantung platform | Vercel, Bun (adapter terverifikasi); Cloudflare dan Netlify sedang mengembangkan adapter, sementara itu memakai integrasi masing-masing |
Vercel dibuat oleh tim yang sama dengan Next.js dan termasuk adapter terverifikasi, sehingga semua fitur (Server Actions, Proxy, Cache Components, ISR) berjalan tanpa konfigurasi tambahan. Ini pilihan termudah untuk belajar.
Deploy ke Vercel
Ada dua jalur:
- Lewat Git (dianjurkan): push proyek ke GitHub, buka dashboard Vercel, pilih "Add New Project", import repositori. Setiap
git pushke branch utama akan otomatis menjadi deploy produksi, dan setiap branch atau pull request lain mendapat Preview Deployment dengan URL sendiri untuk dicoba sebelum digabung. - Lewat CLI:
npm i -g vercel(versi 65.2.0 saat materi ditulis), laluverceldi folder proyek untuk deploy preview, danvercel --produntuk produksi.
Environment variable di Vercel
.env.local tidak ikut ter-upload (dan memang tidak boleh). Isi variabel di Project Settings → Environment Variables, atau lewat CLI vercel env add NAMA production. Vercel membedakan tiga lingkungan: Production, Preview, dan Development. Kamu bisa memberi nilai berbeda, misalnya database terpisah untuk Preview supaya uji coba tidak mengotori data produksi. vercel env pull mengunduh variabel Development ke file lokal.
Ingat dua aturan dari Modul 7: variabel NEXT_PUBLIC_ ditanam saat build, jadi redeploy setelah mengubahnya; dan variabel rahasia jangan pernah diberi awalan itu.
Database untuk produksi
Fungsi serverless di Vercel tidak menyimpan file secara permanen, jadi file:local.db tidak bisa dipakai di produksi. Karena proyek ini memakai driver libSQL, solusinya cukup mengganti URL ke Turso (layanan libSQL di cloud):
turso auth login
turso db create blog-kodingup
turso db show --url blog-kodingup # → libsql://blog-kodingup-xxx.turso.io
turso db tokens create blog-kodingup # → token panjang
Isi DATABASE_URL dan DATABASE_AUTH_TOKEN di Vercel, lalu jalankan drizzle-kit push dan seed dari laptopmu dengan variabel produksi tersebut supaya tabelnya tercipta. Alternatif lain yang umum: Postgres terkelola (Neon, Supabase, Vercel Marketplace) dengan driver Postgres milik Drizzle.
Output standalone untuk server sendiri
Kalau deploy ke VPS atau Docker, set output: 'standalone' di next.config.mjs. Saat build, Next.js melacak file yang benar-benar dibutuhkan lalu menyalinnya ke .next/standalone, lengkap dengan server.js minimal. Folder ini bisa dijalankan tanpa npm install ulang. Dua catatan dari dokumentasi: folder public dan .next/static tidak ikut tersalin otomatis (karena idealnya dilayani CDN), jadi salin manual; dan port/host diatur dengan env PORT dan HOSTNAME.
Untuk deploy multi-instance (beberapa server di belakang load balancer), set NEXT_SERVER_ACTIONS_ENCRYPTION_KEY yang sama di semua instance, karena variabel yang ditangkap Server Action dienkripsi dengan kunci ini.
Static export: kapan bisa
output: 'export' menghasilkan folder out/ berisi HTML, CSS, dan JS murni. Cepat dan murah, tapi tidak mendukung fitur yang butuh server: Server Actions, cookies, Proxy, rewrites/redirects/headers di config, ISR, Route Handler yang membaca Request, Image Optimization dengan loader default, route dinamis tanpa generateStaticParams, dan Draft Mode. Artinya: portofolio statis atau dokumentasi bisa diekspor; blog dengan login admin dan Server Actions seperti proyek akhir tidak bisa.
Domain
Setelah deploy, Vercel memberi alamat nama-proyek.vercel.app. Untuk domain sendiri: buka Project Settings → Domains, tambahkan blogkamu.com (atau vercel domains add blogkamu.com nama-proyek), lalu buat record DNS di penyedia domainmu sesuai yang ditampilkan Vercel. HTTPS dipasang otomatis. Jangan lupa memperbarui NEXT_PUBLIC_SITE_URL ke domain baru dan redeploy, supaya sitemap dan URL canonical memakai alamat yang benar.
Contoh kode
Checklist sebelum deploy, jalankan di laptop:
npm run build # harus sukses tanpa error
npm test # unit/component test hijau
npm run test:e2e # alur penting tetap jalan di build produksi
git status # pastikan .env.local TIDAK ikut ter-stage
Menyiapkan database produksi dan environment variable lewat CLI:
# 1. Buat database Turso dan ambil kredensialnya
turso db create blog-kodingup
turso db show --url blog-kodingup
turso db tokens create blog-kodingup
# 2. Terapkan schema + seed ke database produksi (dari laptop)
DATABASE_URL="libsql://blog-kodingup-xxx.turso.io" \
DATABASE_AUTH_TOKEN="token-panjang" \
npx drizzle-kit push
DATABASE_URL="libsql://blog-kodingup-xxx.turso.io" \
DATABASE_AUTH_TOKEN="token-panjang" \
npm run db:seed
# 3. Hubungkan folder ke proyek Vercel dan isi env
vercel link
vercel env add DATABASE_URL production
vercel env add DATABASE_AUTH_TOKEN production
vercel env add SESSION_SECRET production # nilai baru dari: openssl rand -base64 32
vercel env add ADMIN_PASSWORD production
vercel env add REVALIDATE_SECRET production
vercel env add NEXT_PUBLIC_SITE_URL production # https://blogkamu.com
# 4. Deploy produksi
vercel --prod
# → Production: https://blog-kodingup.vercel.app
Verifikasi setelah deploy, dari terminal:
curl -s -o /dev/null -w "%{http_code}\n" https://blog-kodingup.vercel.app/
# → 200
curl -s -o /dev/null -w "%{http_code} %{redirect_url}\n" https://blog-kodingup.vercel.app/admin
# → 307 https://blog-kodingup.vercel.app/login (Proxy aktif)
curl -s https://blog-kodingup.vercel.app/sitemap.xml | head -5
# → <?xml version="1.0" encoding="UTF-8"?> ... <loc>https://blogkamu.com</loc>
curl -s https://blog-kodingup.vercel.app/api/posts
# → {"count":1,"posts":[{"slug":"halo-dunia",...}]}
Mode standalone untuk VPS:
// next.config.mjs
const nextConfig = {
output: 'standalone',
cacheComponents: true,
partialPrefetching: true,
}
export default nextConfig
npm run build
# → .next/standalone/ berisi: server.js, package.json, node_modules (minimal)
# Salin aset statis yang tidak ikut otomatis
cp -r public .next/standalone/ && cp -r .next/static .next/standalone/.next/
# Jalankan di port 8080, dengarkan semua interface
PORT=8080 HOSTNAME=0.0.0.0 node .next/standalone/server.js
Dockerfile minimal berbasis standalone (gambaran, sesuaikan versi Node dengan servermu):
# Dockerfile
FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:22-alpine
WORKDIR /app
ENV NODE_ENV=production PORT=3000 HOSTNAME=0.0.0.0
COPY --from=build /app/.next/standalone ./
COPY --from=build /app/.next/static ./.next/static
COPY --from=build /app/public ./public
EXPOSE 3000
CMD ["node", "server.js"]
Static export untuk situs yang memang statis (bukan proyek akhir):
// next.config.mjs untuk situs portofolio statis
const nextConfig = {
output: 'export',
images: { unoptimized: true }, // loader default butuh server
}
export default nextConfig
// npm run build → folder out/ siap di-upload ke hosting file statis mana pun
Kesalahan umum
- Lupa mengisi env di hosting. Login gagal atau halaman error 500 di produksi, padahal lancar di laptop. Cocokkan daftar di
.env.exampledengan Environment Variables di Vercel. - Memakai file SQLite di Vercel. Data hilang atau error "read-only file system". Pakai database cloud (Turso, Postgres) untuk produksi.
- Memaksakan static export pada aplikasi dengan Server Actions. Build akan error karena fitur itu butuh server. Pakai Node.js server, Docker, atau Vercel.
- Menjalankan
server.jsstandalone tanpa menyalinpublicdan.next/static. Halaman tampil tanpa CSS dan gambar. Salin keduanya, atau layani lewat CDN. - Memakai secret yang sama dengan laptop. Buat
SESSION_SECRETdan password baru khusus produksi. Kalau secret lokal bocor, produksi tetap aman.
Latihan
- Mudah, Deploy proyek apa pun dari bagian 1 ke Vercel lewat GitHub, lalu buat branch baru, ubah satu teks, push, dan buka URL Preview Deployment-nya.
- Sedang, Buat build
standalonedari proyek akhir di laptop, salin aset statis, jalankan di port 8080, dan pastikancurl localhost:8080/api/postsmengembalikan JSON. - Menantang, Buat dua database Turso (
blog-proddanblog-preview), lalu atur Vercel agar lingkungan Production dan Preview memakai database berbeda. Buktikan dengan membuat artikel di Preview dan memastikan artikel itu tidak muncul di Production.
Lihat solusi
# 1.
git init && git add . && git commit -m "init"
git remote add origin https://github.com/username/proyek.git
git push -u origin main
# Vercel → Add New Project → import repo → Deploy
git checkout -b ubah-judul
# ...ubah teks...
git commit -am "ubah judul" && git push -u origin ubah-judul
# Vercel memberi komentar/URL Preview di pull request atau di tab Deployments
# 2.
# next.config.mjs → tambahkan output: 'standalone'
npm run build
cp -r public .next/standalone/ && cp -r .next/static .next/standalone/.next/
cp local.db .next/standalone/ # server.js melakukan process.chdir() ke foldernya,
# jadi file:local.db dicari di .next/standalone/
PORT=8080 node .next/standalone/server.js
# terminal lain:
curl localhost:8080/api/posts
# → {"count":1,"posts":[...]}
# 3.
turso db create blog-prod
turso db create blog-preview
# Ambil URL & token masing-masing, lalu:
vercel env add DATABASE_URL production # isi URL blog-prod
vercel env add DATABASE_AUTH_TOKEN production
vercel env add DATABASE_URL preview # isi URL blog-preview
vercel env add DATABASE_AUTH_TOKEN preview
# Push schema ke KEDUA database dengan drizzle-kit push.
# Buat artikel lewat URL Preview → buka domain produksi → artikel tidak ada.
Ringkasan
- Next.js bisa dideploy sebagai Node.js server, Docker, static export, atau lewat adapter platform; Vercel adalah adapter terverifikasi dengan dukungan semua fitur.
- Environment variable diisi di dashboard atau
vercel env add, per lingkungan Production/Preview/Development; redeploy setelah mengubahNEXT_PUBLIC_. - Hosting serverless butuh database cloud; dengan libSQL cukup ganti
DATABASE_URLke Turso. output: 'standalone'menghasilkanserver.jsminimal untuk VPS/Docker; salinpublicdan.next/staticsecara manual.- Static export hanya untuk situs tanpa fitur server (tanpa Server Actions, cookies, Proxy, ISR).
- Tambahkan domain di pengaturan proyek, ikuti record DNS dari Vercel, dan perbarui
NEXT_PUBLIC_SITE_URL.