Technology · Next.js
Next.js Deployment
Deploy Next.js apps to production on Vercel, Docker, and other platforms.
TL;DR
- 01Run npm run build to compile your app for production.
- 02Deploy to Vercel with one command or by connecting a Git repo.
- 03Set environment variables in your deployment platform dashboard.
Building for Production
- Build your app for production.
npm run build npm start - Build creates .next folder with optimized files.
- Test production build locally before deploying.
npm run build npm start # Visit http://localhost:3000 - Inspect the build output for page sizes and bundle weights.
npm run build # Route Size First Load JS # / 5 kB 87 kB # /blog/[slug] 3 kB 85 kB - Use output: 'standalone' to create a minimal deployment folder.
// next.config.js module.exports = { output: "standalone" // .next/standalone contains everything needed to run }; - Set NODE_ENV=production when running the server manually.
NODE_ENV=production node .next/standalone/server.js
Vercel Deployment
- Deploy to Vercel (easiest option).
npm install -g vercel vercel - Connect Git repository for automatic deployments.
git push # Automatically deploys to Vercel - Vercel is created by Next.js team.
- Preview deployments are created automatically for every pull request.
- Set environment variables using the Vercel CLI.
vercel env add DATABASE_URL production vercel env add NEXT_PUBLIC_API_URL production - Override the build command in vercel.json if needed.
{ "buildCommand": "npm run build", "outputDirectory": ".next" }
Docker Deployment
- Create Dockerfile for Docker deployment.
FROM node:18-alpine WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build EXPOSE 3000 CMD ["npm", "start"] - Build and run Docker image.
docker build -t my-app . docker run -p 3000:3000 my-app - Use multi-stage builds to reduce the final image size.
FROM node:18-alpine AS builder WORKDIR /app COPY . . RUN npm ci && npm run build FROM node:18-alpine AS runner COPY --from=builder /app/.next/standalone ./ CMD ["node", "server.js"] - Pass environment variables at container runtime.
docker run -p 3000:3000 -e DATABASE_URL=postgres://... my-app - Use docker-compose for local development with a database.
services: app: build: . ports: ["3000:3000"] db: image: postgres:15 environment: POSTGRES_PASSWORD: secret
Environment Variables
- Set environment variables in deployment platform.
# Vercel dashboard vercel env add DATABASE_URL vercel env add NEXT_PUBLIC_API_URL - Use .env.production for local production testing.
# .env.production DATABASE_URL=postgresql://prod-db NEXT_PUBLIC_API_URL=https://api.prod.com - Prefix public variables with NEXT_PUBLIC_ to expose to the browser.
NEXT_PUBLIC_STRIPE_KEY=pk_live_abc123 DATABASE_URL=postgres://secret # server-only - Validate required env variables at startup to catch missing config early.
// lib/env.ts if (!process.env.DATABASE_URL) { throw new Error("DATABASE_URL is required"); } - Store secrets in your CI/CD platform and never commit them to Git.
# GitHub Actions env: DATABASE_URL: ${{ secrets.DATABASE_URL }}
Performance Optimization
- Enable Image Optimization for faster images.
import Image from 'next/image'; <Image src="/photo.jpg" alt="Photo" width={800} height={600} priority /> - Use static exports for fully static sites with no server needed.
// next.config.js module.exports = { output: "export" // Creates an out/ folder you can host on any CDN }; - Enable compression for smaller HTTP responses.
module.exports = { compress: true // enabled by default in production }; - Configure CDN caching for static assets.
module.exports = { headers: async () => [ { source: "/_next/static/(.*)", headers: [{ key: "Cache-Control", value: "public, max-age=31536000, immutable" }] } ] }; - Run lighthouse audits against the deployed production URL.
npx lighthouse https://your-app.vercel.app --output html
Tip: Use Vercel for simplest deployment — it's optimized for Next.js and includes preview deployments.
Warning: Never commit .env.production files — use your deployment platform's secret management.