Att driftsätta Next.js
En genomgång av dina alternativ för att köra Next.js i produktion: Vercel, statisk export till VPS, Docker och Node-server på egen hand.
Next.js ger dig flera sätt att köra din applikation i produktion, och valet är inte självklart. Vercel är det uppenbara förstahandsvalet, men det passar inte alla projekt eller alla budgetar. Statisk export, Docker och en traditionell Node-server på VPS är reella alternativ med tydliga kompromisser. Den här guiden går igenom alla fyra, visar hur de sätts upp i praktiken och hjälper dig avgöra vilket som passar ditt projekt.
Dina alternativ
| Alternativ | Komplexitet | Kostnad | Kontroll | Cold starts |
|---|---|---|---|---|
| Vercel | Låg | Variabel (per anrop) | Låg | Ja, på Hobby/Pro |
| Statisk export + VPS | Medel | Fast, låg | Hög | Nej |
| Docker | Hög | Fast, varierar efter host | Mycket hög | Nej |
| VPS med Node-server | Medel | Fast, låg | Hög | Nej |
Den centrala avvägningen handlar om tre axlar: developer experience, kostnadsprediktabilitet och infrastrukturkontroll. Vercel maximerar developer experience men offrar kostnadsprediktabilitet när trafiken beter sig oväntat. Statisk export och VPS-alternativ ger fast månadskostnad och full kontroll, men kräver att du hanterar infrastrukturen själv. Docker lägger till containeriseringens fördelar men ökar komplexiteten ytterligare. Det finns inget universellt rätt svar, bara rätt svar för din situation.
Vercel
Vercel är plattformen som byggde Next.js, och det märks. Integrationen är djupare än vad någon tredjeparts host kan matcha. Du pekar Vercel på ditt Git-repo och sedan är det klart: varje push till main triggar ett produktionsdeploy, varje pull request får en unik preview-URL med ett eget domännamn. Inga Dockerfiler, inga CI-pipelines att underhålla, inga serverinställningar att hålla koll på.
Zero-config är inte ett tomord. Vercel känner automatiskt igen Next.js och konfigurerar serverless functions för varje API-route och Server Component, sätter upp edge-caching för statiska assets, hanterar SSL-certifikat och konfigurerar HTTP/2. En ny utvecklare kan deploya sin första Next.js-applikation på under fem minuter.
Deploy-arbetsflöde
Det enklaste arbetsflödet kräver bara Git:
git add .
git commit -m "ny funktion"
git push origin main
Vercel fångar pushen via webhook, kör bygget och byter trafiken till den nya versionen utan driftstopp. Om du vill deploya manuellt eller från en CI-pipeline:
npm install -g vercel
vercel --prod
Preview-deploys per branch är ett av Vercels starkaste argument. När du skapar en pull request dyker en URL upp i GitHub-interfacet, direkt kopplad till koden i den branchen. Teamet kan klicka runt i den faktiska applikationen, inte en lokal miljö, innan koden mergas.
Faktureringsbeteendet du behöver förstå
Vercel fakturerar per serverless function invocation. Det innebär att varje gång en API-route, en Server Component som renderas dynamiskt, eller någon annan serverlogik körs, räknas det som en anrop som kostar pengar.
Under normal drift är detta förutsägbart och prisvärt. Problemet uppstår när trafiken beter sig oväntat. En DDoS-attack, en felkonfigurerad crawler som hamrar din API-routes, eller en viral länk som skickar tio gånger mer trafik än vanligt kan generera tusentals function invocations på kort tid. Räkningen kan växa snabbt, och fakturan för månaden ser ut på ett sätt du inte förväntade dig.
Ett dokumenterat, verkligt problem som Next.js-communityt diskuterar regelbundet. Inte ett hypotetiskt scenario.
Den primära motåtgärden är att byta till statisk export. När din applikation exporteras som statiska filer finns det inga serverless functions att anropa. Attacken eller crawlern träffar statiska filer som servas från Vercels CDN till en bråkdel av kostnaden, eller ingen kostnad alls för statisk serving på många planer.
En partiell skyddsåtgärd om du behöver serverlogiken är att sätta ett utgiftsgräns i Vercel-dashboarden:
- Gå till Settings i ditt Vercel-projekt
- Välj Billing
- Aktivera Spend Limits och sätt ett månadstak
Det stoppar inte anropen, men det stoppar fakturan från att växa obegränsat. Var medveten om att det innebär att din applikation slutar svara om gränsen nås.
När Vercel passar
Vercel är rätt val för de flesta projekt under uppbyggnadsfasen och för applikationer med förutsägbar trafik. Preview-deploys per branch är svåra att ersätta för team som arbetar med pull requests. Om din applikation kräver serverlogik och du kan uppskatta trafikvolymen med rimlig precision är Vercel fortfarande det enklaste alternativet.
Statisk export till VPS
Statisk export innebär att Next.js körs som ett byggverktyg snarare än en server. Resultatet är en katalog med HTML-, CSS- och JavaScript-filer som kan servas av vilken webbserver som helst: Nginx, Apache, Caddy, ett CDN direkt, eller ett objekt-storage som S3.
Konfiguration
Aktivera statisk export i next.config.js:
/** @type {import('next').NextConfig} */
const nextConfig = {
output: "export",
trailingSlash: true,
};
module.exports = nextConfig;
trailingSlash: true säkerställer att /om genereras som om/index.html snarare än om.html, vilket fungerar bättre med de flesta webbservrar.
Bygg och exportera:
npm run build
Next.js lägger resultatet i out/-katalogen. Den katalogen är allt du behöver deploya.
Nginx-konfiguration
En minimal men produktionsklar Nginx-konfiguration som servar out/-katalogen med korrekta cache-headers:
server {
listen 80;
server_name dittdomän.se;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name dittdomän.se;
ssl_certificate /etc/letsencrypt/live/dittdomän.se/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/dittdomän.se/privkey.pem;
root /var/www/dittdomän/out;
index index.html;
# Statiska assets med innehållshash i filnamnet kan cachas länge
location /_next/static/ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
# Bilder och andra publika assets
location /images/ {
expires 30d;
add_header Cache-Control "public";
}
# HTML-filer ska inte cachas aggressivt
location / {
try_files $uri $uri/ $uri/index.html =404;
add_header Cache-Control "public, max-age=0, must-revalidate";
}
}
Notera separationen av cache-strategier. Next.js lägger ett innehållsbaserat hash i filnamnet för alla bundlade JavaScript- och CSS-filer under /_next/static/. Det innebär att dessa filer kan cachas i ett år utan att webbläsaren riskerar att använda föråldrade versioner: när koden ändras ändras filnamnet. HTML-filerna däremot pekar alltid på den senaste versionen av dessa assets och ska inte cachas länge.
Cloudflare som skyddslager
Cloudflare framför din VPS ger tre saker: DDoS-skydd, global CDN och gratis SSL. Konfigurationen är enkel:
- Lägg till din domän i Cloudflare och byt namnservrar hos din domänregistrar
- Cloudflare visar din VPS-IP som A-post-mål
- Slå på proxying (den orangefärgade molnikonen i DNS-inställningarna)
Med proxying aktiverat ser angripare Cloudflares IP-adresser, inte din VPS. Cloudflares DDoS-skydd absorberar attacken innan trafiken når din server. För ett statiskt site är detta en gratis och effektiv skyddsmekanism.
Under Settings i Cloudflare kan du aktivera "Under Attack Mode" vid aktiva attacker, vilket kräver en JavaScript-utmaning innan besökare når sidan.
Begränsningar
Statisk export är inte rätt val för alla projekt. Dessa funktioner slutar fungera:
- API Routes (
app/api/) och Route Handlers medPOST,PUTellerDELETEfinns inte i exporten - ISR (Incremental Static Regeneration) fungerar inte, sidor kan bara revalideras vid nästa build
- Dynamisk rendering vid request-tid finns inte,
cookies(),headers()ochsearchParamsfungerar inte på servern - Middleware som modifierar responses kan inte köras, det finns ingen server att köra det på
När statisk export passar
Statisk export är rätt val för innehåll som kan bestämmas fullt ut vid byggtid: marknadsföringssidor, dokumentationssajter, bloggar, portfoliosidor, landningssidor. Om din data uppdateras sällan eller om du kan trigga ett nytt bygge när data ändras är statisk export ett utmärkt val. Sajter som denna, nextjs.nu, är ett tydligt exempel.
Docker
Docker-alternativet gör din Next.js-applikation till en container som kan köras var som helst: din lokala dator, en VPS, ett Kubernetes-kluster, en managed container-tjänst som Google Cloud Run eller AWS ECS.
Standalone output
Next.js har ett output-läge kallat standalone som är gjort för containerisering. Det kopierar bara de filer som faktiskt behövs för att köra servern, inklusive nödvändiga delar av node_modules, utan att ta med hela node_modules-trädet. Det resulterar i en avsevärt mindre produktionsimage.
Aktivera i next.config.js:
/** @type {import('next').NextConfig} */
const nextConfig = {
output: "standalone",
};
module.exports = nextConfig;
Dockerfile
En produktionsklar multi-stage Dockerfile:
FROM node:20-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV PORT=3000
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
CMD ["node", "server.js"]
Multi-stage bygget håller nere imagestorleken. Det första steget (deps) installerar beroenden. Det andra steget (builder) kör Next.js-bygget med tillgång till alla devDependencies. Det tredje steget (runner) kopierar bara standalone-outputen och de statiska filerna, inte hela källkoden eller det kompletta node_modules-trädet.
Bygg och kör lokalt:
docker build -t min-nextjs-app .
docker run -p 3000:3000 min-nextjs-app
Deploy i produktion
Med en container-registry som GitHub Container Registry eller Docker Hub kan du integrera med ett CI-system:
docker build -t ghcr.io/ditt-org/min-app:$(git rev-parse --short HEAD) .
docker push ghcr.io/ditt-org/min-app:$(git rev-parse --short HEAD)
På en VPS med Docker installerat:
docker pull ghcr.io/ditt-org/min-app:senaste-hash
docker stop min-nextjs-app || true
docker rm min-nextjs-app || true
docker run -d \
--name min-nextjs-app \
--restart unless-stopped \
-p 3000:3000 \
ghcr.io/ditt-org/min-app:senaste-hash
När Docker passar
Docker är rätt val när du redan har containerinfrastruktur. Om ditt team använder Kubernetes, om du kör flera tjänster med Docker Compose, eller om din CI/CD-pipeline redan bygger och testar containers är det naturligt att inkludera Next.js i samma flöde. Det ger konsekvent miljöhantering och reproducerbara deployer oberoende av serverns konfiguration.
Docker är också ett bra val för applikationer som behöver SSR eller API-routes men inte passar Vercels faktureringsmodell, och där teamet föredrar containerabstraktion framför direkthantering av processer på en server.
VPS med Node-server
Det enklaste alternativet till Vercel för applikationer som behöver serverlogik är att köra Next.js direkt med Node på en VPS, hanterat med PM2. PM2 är en process manager för Node.js som håller din applikation igång, startar om den vid krascher och hanterar loggar.
Bygge och start
Bygg och starta produktionsservern:
npm run build
npm start
npm start kör next start som startar Next.js HTTP-servern på port 3000. PM2 wrapprar den processen:
pm2 start npm --name "nextjs-app" -- start
pm2 save
pm2 startup
pm2 save sparar processlistans tillstånd. pm2 startup genererar ett kommando som du kör som root för att PM2 ska starta automatiskt efter omstart.
Ecosystem-fil
För mer kontroll, skapa en ecosystem.config.js i projektets rot:
module.exports = {
apps: [
{
name: "nextjs-app",
script: "npm",
args: "start",
env: {
NODE_ENV: "production",
PORT: 3000,
},
max_memory_restart: "1G",
restart_delay: 3000,
max_restarts: 10,
},
],
};
Starta med ecosystem-filen:
pm2 start ecosystem.config.js
max_memory_restart skyddar mot minnesläckor som annars skulle kräva manuell inblandning. restart_delay ger applikationen tid att starta klart innan PM2 räknar ett misslyckat startförsök.
Nginx som reverse proxy
Next.js-servern lyssnar på port 3000. Nginx sitter framför och hanterar SSL och dirigerar trafiken:
server {
listen 80;
server_name dittdomän.se;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name dittdomän.se;
ssl_certificate /etc/letsencrypt/live/dittdomän.se/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/dittdomän.se/privkey.pem;
location /_next/static/ {
expires 1y;
add_header Cache-Control "public, immutable";
proxy_pass http://localhost:3000;
}
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Headern X-Forwarded-For är viktig om din applikation behöver den verkliga IP-adressen bakom proxyn, exempelvis för rate limiting eller loggning.
Deploy-rutin
En enkel men effektiv deploy-rutin via SSH:
ssh användare@din-server \
"cd /var/www/nextjs-app && \
git pull origin main && \
npm ci && \
npm run build && \
pm2 restart nextjs-app"
För noll driftstopp kan du använda PM2:s inbyggda cluster mode med reload istället för restart, men det kräver att applikationen är stateless.
När Node-server på VPS passar
VPS med Node och PM2 är rätt val när du behöver SSR eller API-routes men inte vill ha Vercels faktureringsmodell, och när du inte har befintlig containerinfrastruktur som gör Docker till ett naturligt val. Det är det enklaste alternativet som ger full serverkontroll: en server, en process, full tillgång till loggar och systeminformation utan extra abstraktionslager.
Rekommendation
För de flesta projekt är Vercel det rätta valet att börja med. Zero-konfiguration, preview-deploys per branch och omedelbara rollbacks ger ett developer experience som är svårt att motivera bort. Vercel hanterar infrastrukturen åt dig och du kan fokusera på applikationen.
Brytpunkten är kostnadsprediktabilitet. När serverless function-kostnader börjar bli oförutsägbara, oavsett om det beror på ökad last eller på oväntad trafik som attacker eller felkonfigurerade crawlers, ger statisk export med Cloudflare-skydd på en VPS full kontroll till en fast månadskostnad. Den kombinationen är robust och billig för innehåll som kan bestämmas vid byggtid.
Docker eller VPS med Node fyller utrymmet när du behöver SSR utan Vercels faktureringsmodell. Docker passar bättre om du redan har containerinfrastruktur eller kör i Kubernetes. VPS med Node och PM2 passar bättre om du vill ha enkelhet utan containerabstraktion. Båda ger dig en server du kontrollerar fullt ut, med förutsägbara kostnader och utan cold starts.
