kodingup.camp

Beranda/Next.js Mastery: Full-Stack, Auth & Deploy

Deploy

Modul 10 dari 115 menit bacaDeployment

Isi modul

    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:

    1. Lewat Git (dianjurkan): push proyek ke GitHub, buka dashboard Vercel, pilih "Add New Project", import repositori. Setiap git push ke branch utama akan otomatis menjadi deploy produksi, dan setiap branch atau pull request lain mendapat Preview Deployment dengan URL sendiri untuk dicoba sebelum digabung.
    2. Lewat CLI: npm i -g vercel (versi 65.2.0 saat materi ditulis), lalu vercel di folder proyek untuk deploy preview, dan vercel --prod untuk 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

    1. Lupa mengisi env di hosting. Login gagal atau halaman error 500 di produksi, padahal lancar di laptop. Cocokkan daftar di .env.example dengan Environment Variables di Vercel.
    2. Memakai file SQLite di Vercel. Data hilang atau error "read-only file system". Pakai database cloud (Turso, Postgres) untuk produksi.
    3. Memaksakan static export pada aplikasi dengan Server Actions. Build akan error karena fitur itu butuh server. Pakai Node.js server, Docker, atau Vercel.
    4. Menjalankan server.js standalone tanpa menyalin public dan .next/static. Halaman tampil tanpa CSS dan gambar. Salin keduanya, atau layani lewat CDN.
    5. Memakai secret yang sama dengan laptop. Buat SESSION_SECRET dan password baru khusus produksi. Kalau secret lokal bocor, produksi tetap aman.

    Latihan

    1. 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.
    2. Sedang, Buat build standalone dari proyek akhir di laptop, salin aset statis, jalankan di port 8080, dan pastikan curl localhost:8080/api/posts mengembalikan JSON.
    3. Menantang, Buat dua database Turso (blog-prod dan blog-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

    Video pendamping

    Kalau penjelasan di atas belum masuk, tonton ini. Video dari kanal YouTube pihak lain.

    Cara Deploy Next.js ke Vercel untuk PemulaWarung Kode · Bahasa IndonesiaBuka di YouTube

    Kuis pemahaman

    Pilih satu jawaban per soal. Penjelasan muncul setelah kamu menjawab.