Gidsen

404-fouten na het publiceren van je website of app oplossen

Als je app lokaal werkt maar pagina’s na het deployen een 404 geven, is de meest voorkomende oorzaak ontbrekende single-page app (SPA)-routing: de server zoekt naar een bestand genaamd /dashboard dat niet bestaat, omdat die route alleen in JavaScript bestaat. De oplossing is een fallbackregel die index.html serveert voor app-routes. Andere oorzaken zijn bestanden die ontbreken in de buildoutput, hoofdlettergevoelige paden, verschillen in slashes aan het eind, een verkeerd basispad, en API-routes die nooit zijn gedeployd.

Begin met precies noteren welke URL een 404 geeft en hoe je daar kwam. Het patroon wijst direct naar de oorzaak.

Stap 1: zoek het patroon

Wat je zietMeest waarschijnlijke oorzaakGa naar
Startpagina werkt; klikken op links werkt; verversen of een directe link geeft 404Geen SPA-fallbackStap 2
Elke pagina geeft 404, ook de startpaginaVerkeerde map gepubliceerd, of de build is niet gedeploydStap 3
Pagina’s laden, maar afbeeldingen, lettertypes of scripts geven 404Bestanden ontbreken in de build, of verkeerde padenStap 4
Werkt met /over/, faalt met /over (of andersom)Afhandeling van slashes aan het eindStap 5
/Over faalt maar /over werktHoofdlettergevoelige serverStap 4
Pagina laadt, maar dataverzoeken naar /api/... geven 404API niet gedeployd of niet gerouteerdStap 6
Oude URL’s van een vorige site geven 404Ontbrekende redirectsStap 7
Alleen op een eigen domeinDNS- of domeininstellingStap 8

Om de echte statuscode te zien, open je de ontwikkelaarstools (klik met rechts → Inspecteren), ga je naar het tabblad Netwerk, laad je opnieuw en kijk je naar de status van het eerste verzoek.

Stap 2: voeg de SPA-fallback toe

Dit is de klassieke. In een React-, Vue- of Svelte-single-page app heeft de server maar een handvol echte bestanden: index.html en wat JavaScript en CSS. Routes zoals /dashboard of /projects/42 worden afgehandeld door een router in de browser.

  • Klikken op een link werkt: de router past de URL aan en tekent de nieuwe pagina zonder de server erbij te halen.
  • Verversen of een link direct openen faalt: de browser vraagt de server om /dashboard, de server heeft dat bestand niet en geeft 404.

De oplossing is een regel die zegt: als het verzoek niet overeenkomt met een echt bestand, serveer index.html met status 200 en laat de router het overnemen. Hoe je dat toevoegt hangt af van de host (controleer de actuele documentatie van je host, want details veranderen):

HostGebruikelijke fallbackregel
NetlifyEen _redirects-bestand in de gepubliceerde map met /* /index.html 200
VercelEen rewrite in vercel.json van alle paden naar /index.html (frameworkpresets regelen dit vaak al)
Cloudflare PagesServeert standaard een SPA-achtige fallback als er geen 404.html op het hoogste niveau staat
Nginxtry_files $uri $uri/ /index.html; in het location /-blok
ApacheEen rewrite-regel in .htaccess die niet-bestandsverzoeken naar index.html stuurt
GitHub PagesGeen server-side rewrites; gangbare omweggen zijn hash-routing of een 404.html dat doorverwijst

Zorg dat de regel echte bestanden niet opslokt: verzoeken naar /assets/app.js moeten nog steeds het JavaScript-bestand teruggeven. Als ze index.html teruggeven, krijg je een witte pagina met de fout “Failed to load module script”. Zie een witte lege pagina oplossen.

Geef de router ook een catch-all-route, zodat URL’s die op geen enkele pagina passen een vriendelijke “Pagina niet gevonden” tonen in plaats van niets.

Als je serverinstellingen niet kunt wijzigen, dan vermijdt hash-routing (URL’s zoals /#/dashboard) het probleem, omdat het deel na # nooit naar de server wordt gestuurd. Het is een omweg, geen eerste keuze: de URL’s zijn lelijker en minder vriendelijk voor zoekmachines.

Frameworks die pagina’s op de server renderen of op buildtijd genereren (Next.js, Astro en vergelijkbare) hebben meestal echte bestanden of serverroutes voor elke pagina, dus dit specifieke probleem komt daar minder vaak voor. Hun equivalent is een pagina die nooit op buildtijd is gegenereerd.

Stap 3: controleer wat er echt is gedeployd

Als alles 404 geeft, serveert de server waarschijnlijk niet je gebouwde app.

  • De juiste map. De host moet de buildoutput publiceren (meestal dist voor Vite, build voor Create React App, out voor een statische Next.js-export), niet de hoofdmap van het project.
  • De build is gelukt. Lees het deploylog. Als de build mislukte, heeft de host misschien niets of een oude versie gedeployd.
  • index.html staat op het hoogste niveau van de gepubliceerde map, niet in een submap.
  • Het basispad klopt. Als de app wordt geserveerd vanaf voorbeeld.nl/app/, moet hij met dat basispad zijn gebouwd (Vite’s base, React Routers basename), anders missen alle routes en assets.

Stap 4: los ontbrekende bestanden en verkeerde paden op

Als pagina’s laden maar assets 404 geven:

  • Hoofdlettergevoeligheid. macOS en Windows behandelen Logo.png en logo.png meestal als hetzelfde bestand. De meeste Linux-servers niet. Zorg dat elke verwijzing de exacte bestandsnaam overneemt.
  • Bestanden buiten de build. In Vite worden bestanden in public/ ongewijzigd gekopieerd en verwijs je ernaar vanaf de root (/logo.png). Bestanden die in code worden geïmporteerd, worden meegebundeld. Een bestand ergens anders in het project wordt mogelijk helemaal niet gedeployd.
  • Relatieve paden. images/foto.jpg wordt ten opzichte van de huidige URL opgelost, dus het breekt op /blog/post-1. Gebruik /images/foto.jpg.
  • Geüploade bestanden opgeslagen op de lokale schijf. Als uploads van gebruikers in de map van de server zijn geschreven, verdwijnen ze bij een nieuwe deployment. Gebruik echte bestandsopslag.

Stap 5: behandel slashes aan het eind consistent

/over en /over/ zijn verschillende URL’s. Hosts verschillen in of ze de slash toevoegen of verwijderen, en een mismatch met je links of je router kan 404’s of redirect-lussen veroorzaken. Kies één stijl, laat je links die gebruiken, en configureer de host om de andere vorm door te verwijzen. Consistentie helpt ook zoekmachines, die anders twee kopieën van elke pagina zien.

Stap 6: los API-routes op die 404 geven

Als de pagina laadt maar het tabblad Netwerk /api/...-verzoeken met 404 toont:

  • De backend is niet gedeployd. Een statische host serveert alleen bestanden; een backend moet ergens draaien.
  • Het pad wordt in productie anders gerouteerd. In ontwikkeling kan een proxy /api naar een aparte server hebben doorgestuurd. In productie heeft de host een gelijkwaardige rewrite nodig, of moet de frontend het echte adres van de API aanroepen.
  • De SPA-fallback heeft het opgevangen. Een API-verzoek dat index.html teruggeeft met status 200 betekent dat de fallbackregel te breed is. Sluit /api/* ervan uit.

De gepubliceerde app krijgt 404 op de verzoeken naar /api/orders, maar ze werken in de preview. Controleer hoe /api wordt gerouteerd in de preview versus de gepubliceerde app, en zorg dat de gepubliceerde frontend de backend op dezelfde manier bereikt.

Stap 7: stuur oude URL’s door

Als je bent verhuisd van een andere site of de structuur hebt aangepast, geven oude URL’s die mensen en zoekmachines nog gebruiken een 404. Voeg een 301- (permanente) redirect toe van elke oude URL naar de nieuwe plek. Houd een lijst bij en test na de lancering een steekproef. Onze gids over het migreren van een WordPress-site beschrijft hoe je die lijst opstelt.

Stap 8: controleer het domein

Als de app werkt op het adres van de host maar een 404 geeft op je eigen domein, wijst het domein mogelijk naar het verkeerde project, of heeft de host het domein nog niet aan je site gekoppeld. Controleer de DNS-records en de domeininstellingen van de host. Zie hoe je een eigen domein koppelt.

Maak je echte 404-pagina nuttig

Sommige 404’s zijn correct: iemand heeft een URL verkeerd getypt. Maak die pagina dan behulpzaam:

  • Een korte boodschap en een link naar de startpagina en belangrijke secties
  • Een zoekveld, als de site zoekfunctie heeft
  • Dezelfde header en navigatie als de rest van de site

Geef, waar je setup dat toestaat, een echte 404-status terug voor pagina’s die niet bestaan. Een “niet gevonden”-bericht met status 200 is wat zoekmachines een soft 404 noemen; het verspilt hun crawltijd en kan de indexering in de war sturen.

Veelgemaakte fouten

  • Alleen testen door te klikken. Test altijd door diepe URL’s in een nieuw tabblad te plakken en te verversen.
  • Een fallback die alles opvangt. Assets en API-routes geven index.html terug, wat witte pagina’s en verwarrende API-fouten veroorzaakt.
  • Afwijkende hoofdletters die alleen op de server breken.
  • De bronmap deployen in plaats van de buildoutput.
  • URL’s herstructureren zonder redirects. Elke oude link wordt een 404.

404’s in Mythex

In Mythex publiceer je vanuit de werkruimte, en statische frontends worden als statische sites gedeployd. Als een gepubliceerde pagina een 404 geeft, geef de agent dan de exacte URL, of het gebeurt bij verversen of bij klikken, en wat het tabblad Netwerk toont, en vraag hem de routing te controleren. Publiceer opnieuw na de fix, want de live app is een momentopname tot je opnieuw publiceert. Als je het project recent hebt gewijzigd en de live site oud lijkt, publiceer dan opnieuw en ververs hard. Gebruik Repareren met AI in het publicatiedialoogvenster als de build mislukt. Zie Hoe publiceer je en Publicatie-problemen oplossen in de documentatie, en onze gids over het debuggen van een met AI gebouwde app.

404-checklist

  • Exact genoteerd welke URL’s een 404 geven, en of bij klikken, verversen of allebei
  • SPA-fallback serveert index.html voor app-routes, met status 200
  • Fallback sluit echte bestanden en /api/* uit
  • Router heeft een catch-all-route voor “niet gevonden”
  • De buildoutputmap is wat wordt gepubliceerd, en de build is gelukt
  • Basispad klopt met waar de app wordt geserveerd
  • Hoofdlettergebruik van bestandsnamen klopt met elke verwijzing
  • Asset-paden beginnen met /
  • Stijl van slashes aan het eind is consistent
  • API-routes zijn gedeployd en in productie gerouteerd
  • 301-redirects voor oude URL’s
  • Diepe links getest door ze in een nieuw tabblad te plakken

Veelgestelde vragen

Waarom krijg ik een 404 als ik een pagina in mijn React-app ververs?

In een single-page app bestaan routes zoals /dashboard alleen in JavaScript. Klikken op een link werkt omdat de router dat in de browser afhandelt, maar bij verversen vraagt de browser de server om een /dashboard-bestand dat niet bestaat. De oplossing is een fallbackregel die index.html serveert voor app-routes.

Hoe voeg ik een SPA-fallback toe op Netlify, Vercel of Nginx?

Op Netlify voeg je een _redirects-bestand toe met /* /index.html 200. Op Vercel voeg je een rewrite toe in vercel.json die alle paden naar /index.html stuurt. Op Nginx gebruik je try_files $uri $uri/ /index.html; in het location-blok. Controleer de documentatie van je host, want regels veranderen.

Waarom geven mijn afbeeldingen of bestanden een 404 na het deployen?

Meestal staat het bestand niet in de buildoutput, komt de hoofdlettergebruik van het pad niet overeen (servers zijn vaak hoofdlettergevoelig waar je laptop dat niet is), of is het pad relatief terwijl het met een schuine streep moet beginnen.

Moet een ontbrekende pagina een echte 404-status teruggeven?

Ja. Toon een behulpzame pagina voor niet-gevonden, maar met een 404-status waar je setup dat toestaat. Zoekmachines zien een ‘niet gevonden’-bericht met status 200 als een soft 404, wat crawltijd verspilt en de indexering in de war kan sturen.

Mythex · Pricing · Bouw alles met AI · Website- en app-templates · Mythex vergeleken · Woordenlijst voor apps bouwen met AI · Gratis tools voor apps bouwen met AI · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)