Skip to content

Vite deployment errorVite “Failed to load module script”: MIME type of “text/html”

The site goes blank, often right after a new deploy, and the console says it expected a JavaScript module but the server answered with text/html. The browser asked for a script and got a web page instead. Here’s why that happens, in Vite’s and Netlify’s words, and the fix, or hand it over at a fixed price.

Short answer

The browser asked for one of your JavaScript files and got HTML back. Usually the visitor has old HTML pointing at chunk files the latest deploy removed, and a catch-all rewrite answers the missing file with index.html. Serve the HTML with Cache-Control: no-cache, as Vite says. We also reload the page on Vite’s vite:preloadError event, and check the base setting if the app lives in a subfolder.

Why the browser got HTML, and the fix

  1. 01

    Old HTML asks for files the new deploy removed

    “When a new deployment occurs, the hosting service may delete the assets from previous deployments.” Vite, Load error handling

    A visitor who loaded the page before the deploy still has HTML that points at the old files, which the host may have deleted. Vite says to set Cache-Control: no-cache on the HTML file, so browsers fetch the new one, and shows this event for handling the failed import. We also reload the page there so visitors get the new files:

    window.addEventListener('vite:preloadError', (event) => {
      window.location.reload() // for example, refresh the page
    })
  2. 02

    The catch-all rewrite answers a missing file with index.html

    “This will effectively serve the index.html instead of giving a 404 no matter what URL the browser requests.” Netlify, Rewrites and proxies

    Single-page apps usually have a rewrite such as /* /index.html 200 so that links to inner pages work. It also answers a request for a script file that doesn’t exist with index.html, which the browser refuses as a module. Files that do exist are still served, unless the rule ends in an exclamation mark, which Netlify says redirects even when the URL matches a static file. We also check that the rule is the last one in the list.

  3. 03

    The app lives in a subfolder but base is still /

    “Base public path when served in development or production.” Vite, Shared options: base

    If the app is served from a path such as /app/, set base to that path in the Vite config, then build again. We also see this when base is left as /: the built HTML asks for files at the site root, and the request gets a page instead of your script.

Checked against the vendor’s docs on : Vite docs: Load error handling; Vite docs: base; Netlify docs: Rewrites and proxies.

Rather hand it over?

Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.

Related: Lovable app blank after publishing · Page not found on refresh · Build failed on Netlify or Vercel

Questions

More on this error

Why does a hard refresh fix it for me?

A hard refresh loads the newest HTML, which points at the files that exist now. Your visitors won’t do that, which is why the HTML needs Cache-Control: no-cache, and why we also make the page reload itself on vite:preloadError.

Should I remove the catch-all rewrite?

No. Without it, links to inner pages of a single-page app return 404. Keep it as the last rule, without an exclamation mark, and fix the stale HTML instead.

Can you fix it for me?

If one bug is the whole problem, the App Fix Ticket covers it: a written diagnosis first, then the fix. If the app has more going on, the Launch Check is a written check of the whole app. Each issue found is rated critical, high, medium or low, with where it is and how it was confirmed. No issues worth fixing, no charge. If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way.

A different error?

Describe it and get a written quote

Send the error and what you were doing. You get a written scope, a fixed price and a timeline; we reply by email, usually within one business day.