Tør du trykke deploy, når alle faner er lukket og ingen kigger?
Det føles lidt som at tage på cykelferie uden værktøj. På parkeringspladsen ser alt fint ud, kæden kører, dækkene er pumpede, og du har vind i håret. 20 km senere står du i grøften med et fladt dæk og et meget teoretisk forhold til, hvad du kunne have gjort anderledes.
Sådan har jeg det med frontend-deploys.
Jeg har efterhånden haft nok “det virker på min maskine” øjeblikke til, at jeg er begyndt at skrive deploy-checklister til mig selv. Ikke fancy, bare små noter: “husk env vars”, “byg lokalt med samme kommando som CI”, “tjek 404 på deep links”.
I den her tekst gennemgår jeg den version, jeg faktisk bruger før jeg trykker deploy på små frontend-projekter. Den er stack-agnostisk, men jeg nævner Vercel, Netlify og GitHub Pages undervejs, fordi det er dem jeg selv ender på oftest.
Pre-flight: hvad jeg vil have styr på, inden jeg overhovedet bygger
Mit mønster er næsten altid det samme: jeg får lavet “den sidste feature”, alt kører i npm run dev, og fristelsen til bare at smide det på Vercel er stor. De gange jeg har gjort det, er det gået cirka lige så godt som at skifte bremseklodser på bilen dagen før syn uden at teste dem bagefter.
I dag tjekker jeg mindst de her ting, før jeg overhovedet tænker deployment:
- Ingen hårdkodet localhost i koden
Jeg søger efterlocalhost,127.0.0.1og porte som:3000,:5173.
Før:
const API_URL = "http://localhost:3000/api";
Efter:
const API_URL = import.meta.env.VITE_API_URL; // Vite-eksempel
- Node- og package-manager version
Jeg skriver dem i.nvmrcellerenginesipackage.json, så CI ikke bygger med noget helt andet. - Build-scriptet
CI skal kørenpm run build(ellerpnpm build) og ikke et eller andet jeg aldrig bruger lokalt.
Det lyder banalt, men de fleste “produktionen fejler, men dev kører fint” bugs jeg har haft, starter her.
Byg lokalt som CI gør: clean install og production build
Jeg har en dårlig vane med bare at køre npm run build i et miljø, hvor der har ligget node_modules i 100 år. Det er ikke det samme som det CI gør.
I dag tester jeg sådan her, før jeg stoler på noget:
rm -rf node_modules dist .turbo .next
rm package-lock.json # eller pnpm-lock.yaml / yarn.lock hvis du vil teste helt friskt
npm install
npm run build
Hvis buildet fejler her, så var det bare held, at det virkede før. Ikke stabilitet.
Bruger du Vite, Next, Nuxt eller lignende, så kig også lige ned i output-mappen (dist, .next, out):
- Findes der faktisk en
index.htmleller200.html? - Ligner assets-stierne noget, din host forstår? (ingen
file:///eller mærkelige base paths)
MDN har en fin intro til frontend-deployment, hvis du vil have det store billede: MDN deployment intro. Men start med at kunne bygge lokalt uden magi.
Miljøvariabler: det her går næsten altid galt første gang
Den mest klassiske fejl jeg ser (og laver) er env vars, der kun findes i min egen .env, men aldrig i Vercel/Netlify.
Min egen lille huskeliste:
Navngivning og scope
- I Vite skal variabler til frontend starte med
VITE_. - I Next skal de starte med
NEXT_PUBLIC_, hvis de skal ud til browseren. - Filer som
.envkommer ikke automatisk med op i deployment.
Så det, jeg gør, er:
- Opretter env vars i dashboardet
Vercel: Project > Settings > Environment Variables
Netlify: Site configuration > Environment variables
GitHub Pages: typisk ikke til dynamic env, men du kan bruge GitHub Actions secrets til builds. - Bygger igen i CI
Trigger et nyt build efter jeg har sat env vars. Det hjælper ikke at ændre dem, hvis jeg ikke faktisk laver et nyt build. - Logger værdier i build-step (uden hemmeligheder)
En enkelconsole.log("API URL", import.meta.env.VITE_API_URL)i build-venlig kode (ellerprocess.env.NAVNi Node-delen), så jeg kan se i logs, hvad der faktisk er sat.
Jeg har skrevet lidt mere generelt om env-vars problemer i en anden artikel: hvordan du undgår det kaos-API jeg selv startede med. Pointen er den samme her: antag ikke at din host kan gætte, hvad dine env vars skal være.
Routing: SPA, deep links og 404 som kun findes i produktion
Her er en fejl jeg har lavet mindst ti gange:
- Byg en SPA med client-side routing (React Router, Vue Router, etc.).
- Kør den lokalt via dev-server. Alt virker.
- Deploy på Netlify eller Vercel.
- Åbn
/dashboarddirekte. Få en 404 fra hosten.
Der er to ting jeg tjekker nu:
1. Rewrites / fallback
- Vercel: i
vercel.jsoneller projekt-setup sørger jeg for en rewrite af alle ikke-static routes til/index.html. - Netlify: en
_redirectsfil med/* /index.html 200 - GitHub Pages: oftest bedst egnet til simple MPAs, men der findes workarounds med 404.html-tricks.
2. Base path og assets
Hvis du hoster under et subpath, fx https://user.github.io/projekt-navn/, skal du typisk sætte et base-felt (Vite) eller bruge Nexts basePath.
Typisk før-fejl:
export default defineConfig({
// ingen base
});
Efter på GitHub Pages:
export default defineConfig({
base: "/projekt-navn/",
});
Hvis dine CSS- og JS-filer ikke bliver fundet i produktion, starter jeg altid med at kigge på den slags.
API-kald i produktion: CORS, HTTPS og “det virkede jo lokalt”
Det her er næsten sit eget kursus, men min deploy-tjekliste er ret kort:
- Base URL peger ikke på localhost
Søg efterhttp://localhostigen. Er API-URL’en sat via env var til en rigtig host? - HTTPS over det hele
Hvis frontend ligger påhttps, men API påhttp, vil browseren blokere mixed content. - CORS kun fejler i produktion
Lokalt bruger jeg ofte en dev-proxy. I produktion kalder jeg API’et direkte, og så giver det CORS-fejl.
Mit trick her er at åbne Chrome DevTools Network i produktion (ikke kun lokalt). Jeg klikker på et API-kald, ser på Request URL, Response headers og evt. fejl. Jeg har en hel artikel om den tilgang: da jeg første gang åbnede Chrome DevTools Network og alt gav mening.
Caching og gamle filer: deploy uden at deploye
En af de mere irriterende fejl: jeg deployer, men ser stadig den gamle version.
Det er typisk en blanding af:
- Browser-cache
- CDN-cache (Netlify/Vercel)
- Manglende cache-busting i filnavne
Det jeg altid tjekker, når jeg bliver i tvivl:
- Åbn siden i incognito og/eller i en anden browser.
- I DevTools: Network-tab, sæt “Disable cache” til.
- Kig på filnavne: har dine JS/CSS-filer hashes i navnet?
app.4f3c1a.jser bedre endapp.js.
De fleste moderne bundlere (Vite, Webpack, Parcel) tager sig af filnavne, hvis du laver en production build. Men GitHub Pages med håndskrevet HTML og en gammel app.js har ikke den luksus.
Observability light: lidt logs er bedre end ingen
Jeg er ikke på Sentry og fuldt observability-setup i mine små hobbyprojekter. Men jeg prøver at have en eller anden plan for, hvordan jeg opdager fejl i produktion.
Mine minimums-vaner:
- Hold øje med JavaScript errors
Åbn DevTools Console i produktion og klik rundt. Se om der dukker røde errors op, du aldrig så i dev. - Gem evt. fejl i lokal storage
Til små projekter kan jeg finde på at lave en lille error-handler, der logger fejl tillocalStoragemed timestamp, så en bruger kan sende mig dem. - Brug hostens logs
Vercel og Netlify viser build logs, og nogle planer har også function logs. Kig dem igennem første gang du deployer noget nyt.
Jeg har tidligere skrevet om at stole mere på logs end på hukommelse: jeg stoler mere på mine logs end på min hukommelse. Det gælder 100 % også her.
Min hurtige “go/no-go” deploy checkliste
Hvis jeg skal være ærlig, så kører jeg sjældent hele romanen ovenfor igennem systematisk. Men jeg har 12 små spørgsmål i mit hoved, som jeg prøver at svare ja til, før jeg trykker deploy.
1-4: Build og miljø
- Har jeg kørt en clean install og
npm run buildlokalt uden fejl? - Matcher Node-versionen nogenlunde det, CI bruger?
- Er alle env vars, jeg bruger i koden, også sat i Vercel/Netlify/GitHub Actions?
- Har jeg verificeret i logs, at de rigtige env værdier faktisk bruges ved build?
5-8: Routing og API
- Har jeg en 404/rewrites-opsætning, så SPA-routes virker ved direkte load?
- Er der sat korrekt base path, hvis jeg hoster i et subdirectory?
- Er alle API-URLs konfigureret via env vars (ingen hårdkodet localhost)?
- Har jeg testet et API-kald i produktion via DevTools Network og set, at det returnerer det forventede?
9-12: Caching og brugeroplevelse
- Har jeg åbnet sitet i incognito efter et deploy for at se den “rene” version?
- Bruger min bundler hashed filnavne til JS/CSS, så gamle filer ikke hænger fast?
- Har jeg klikket igennem de vigtigste flows i produktion, ikke kun lokalt?
- Har jeg mindst én måde at opdage fejl på (console check, simple logging eller lignende)?
Hvis jeg går igennem listen og må svare “nej” til mere end et par stykker, så ved jeg egentlig godt, at jeg ikke burde trykke deploy endnu. Nogle gange gør jeg det alligevel, men så fortjener jeg sådan set også de bugs, jeg får.
Jeg synes personligt, at en deploy først er godkendt, når jeg kan lukke min laptop, komme ud på cyklen langs kysten og være rimelig sikker på, at telefonen ikke bipper, før jeg er hjemme igen. Hvis ikke jeg har gjort mig den ulejlighed, så er det ikke et uheld, når produktionen brænder, det er bare dovenskab forklædt som optimisme.







Send kommentar
Du skal være logget ind for at skrive en kommentar.