Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I configure Vite's dev server to give 404 errors?

Using Vite's dev server, if I try to access a non-existent URL (e.g. localhost:3000/nonexistent/index.html), I would expect to receive a 404 error. Instead I receive a 200 status code, along with the contents of localhost:3000/index.html.

How can I configure Vite so that it returns a 404 in this situation?

(This question: Serve a 404 page with app created with Vue-CLI, is very similar but relates to the Webpack-based Vue-CLI rather than Vite.)

like image 974
user200783 Avatar asked Dec 05 '25 14:12

user200783


1 Answers

Vite 3

Vite 3.x introduced appType, which can be used to enable/disable the history fallback. Setting it to 'mpa' disables the history fallback while keeping the index.html transform and the 404 handler enabled. The naming is somewhat misleading, as it implies the mode is only for MPAs, but on the contrary, you can use this mode for SPAs:

import { defineConfig } from 'vite'

export default defineConfig({
  appType: 'mpa', // disable history fallback
})

Note the history fallback normally rewrites / to /index.html, so you'd have to insert your own middleware to do that if you want to keep that behavior:

import { defineConfig } from 'vite'

const rewriteSlashToIndexHtml = () => {
  return {
    name: 'rewrite-slash-to-index-html',
    apply: 'serve',
    enforce: 'post',
    configureServer(server) {
      // rewrite / as index.html
      server.middlewares.use('/', (req, _, next) => {
        if (req.url === '/') {
          req.url = '/index.html'
        }
        next()
      })
    },
  }
}

export default defineConfig({
  appType: 'mpa', // disable history fallback
  plugins: [
    rewriteSlashToIndexHtml(),
  ],
})

Vite 2

Vite 2.x does not support disabling the history API fallback out of the box.

As a workaround, you can add a Vite plugin that removes Vite's history API fallback middleware (based on @ChrisCalo's answer):

// vite.config.js
import { defineConfig } from 'vite'

const removeViteSpaFallbackMiddleware = (middlewares) => {
  const { stack } = middlewares
  const index = stack.findIndex(({ handle }) => handle.name === 'viteSpaFallbackMiddleware')
  if (index > -1) {
    stack.splice(index, 1)
  } else {
    throw Error('viteSpaFallbackMiddleware() not found in server middleware')
  }
}

const removeHistoryFallback = () => {
  return {
    name: 'remove-history-fallback',
    apply: 'serve',
    enforce: 'post',
    configureServer(server) {
      // rewrite / as index.html
      server.middlewares.use('/', (req, _, next) => {
        if (req.url === '/') {
          req.url = '/index.html'
        }
        next()
      })

      return () => removeViteSpaFallbackMiddleware(server.middlewares)
    },
  }
}

export default defineConfig({
  plugins: [
    removeHistoryFallback(),
  ],
})

One disadvantage of this plugin is it relies on Vite's own internal naming of the history fallback middleware, which makes this workaround brittle.

like image 185
tony19 Avatar answered Dec 07 '25 19:12

tony19



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!