{"id":13166,"library":"express-history-api-fallback","title":"Express History API Fallback Middleware","description":"express-history-api-fallback is an Express middleware designed to facilitate client-side routing for Single Page Applications (SPAs) that utilize the HTML5 History API. It addresses the common problem of 404 errors when a user directly navigates to a client-side route (e.g., `/app/dashboard`) that doesn't correspond to a static file on the server. The middleware ensures that the main `index.html` (or a specified entry point) is served instead. Currently stable at version 2.2.1, with its last known update around May 2017, the package maintains a highly focused approach. It explicitly serves the fallback only for GET/HEAD requests, for requests likely to be HTML, and only if no other static file or route matches. It leverages Express's `res.sendFile()` for efficient serving. While functional and widely used, its release cadence is dormant, indicating it's a mature, feature-complete library rather than one under active development.","status":"maintenance","version":"2.2.1","language":"javascript","source_language":"en","source_url":null,"tags":["javascript","express","html5","history api","fallback","spa","middleware","connect","pushstate"],"install":[{"cmd":"npm install express-history-api-fallback","lang":"bash","label":"npm"},{"cmd":"yarn add express-history-api-fallback","lang":"bash","label":"yarn"},{"cmd":"pnpm add express-history-api-fallback","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"This package is an Express middleware and relies on Express's request/response objects and `res.sendFile()` method.","package":"express","optional":false}],"imports":[{"note":"The package exports a default function. Attempting a named import will result in an error.","wrong":"import { fallback } from 'express-history-api-fallback'","symbol":"fallback","correct":"import fallback from 'express-history-api-fallback'"},{"note":"Standard CommonJS import pattern. No named exports are available for require().","symbol":"fallback (CommonJS)","correct":"const fallback = require('express-history-api-fallback')"},{"note":"The imported 'fallback' symbol is directly the middleware function. It expects the path and an optional options object as arguments.","symbol":"Middleware Function","correct":"app.use(fallback('index.html', { root }))"}],"quickstart":{"code":"import fallback from 'express-history-api-fallback'\nimport express from 'express'\nimport path from 'path'\n\nconst app = express()\nconst publicPath = path.join(__dirname, 'public') // Assuming 'public' folder for static assets\nconst indexHtmlPath = path.join(publicPath, 'index.html')\n\n// Serve static files first\napp.use(express.static(publicPath))\n\n// Use the history API fallback for all non-static GET/HEAD requests\n// This should come AFTER static file serving and API routes.\napp.use(fallback('index.html', { root: publicPath }))\n\n// Example API route (should be placed before fallback if you want it to be matched)\napp.get('/api/data', (req, res) => {\n  res.json({ message: 'Hello from API!' })\n})\n\nconst PORT = process.env.PORT || 3000\napp.listen(PORT, () => {\n  console.log(`Server listening on port ${PORT}`)\n  console.log(`Serving static files from ${publicPath}`)\n})\n","lang":"javascript","description":"This quickstart demonstrates how to set up `express-history-api-fallback` to serve a single-page application. It configures Express to serve static files from a 'public' directory and then applies the fallback middleware. The fallback ensures that any unhandled GET/HEAD requests (typically client-side routes) return 'index.html', enabling HTML5 History API routing. It also shows the importance of middleware order."},"warnings":[{"fix":"Upgrade to Express v4.8.0 or newer to ensure full compatibility and access to all `res.sendFile()` options.","message":"Older versions of Express (prior to v4.8.0) used `res.sendfile()` instead of `res.sendFile()`. While `express-history-api-fallback` attempts to handle this internally, using a very old Express version might lead to unexpected behavior or limited options. The package specifically notes that only `maxAge` and `root` options are supported with `express@<4.8`.","severity":"breaking","affected_versions":"<4.8.0"},{"fix":"Ensure your middleware chain has `app.use(express.static('public'))` (or similar static file server) before `app.use(fallback('index.html', { root }))`.","message":"The `fallback` middleware must be placed AFTER any `express.static` middleware or API routes that should be handled directly by the server. If placed before, it can intercept static file requests or API calls, serving `index.html` instead.","severity":"gotcha","affected_versions":">=2.0.0"},{"fix":"Use either an absolute path directly: `app.use(fallback(__dirname + '/public/index.html'))` or provide the `root` option for relative paths: `app.use(fallback('index.html', { root: __dirname + '/public' }))`.","message":"When providing a relative `path` argument to `fallback()`, the `root` option must be specified. If `root` is omitted, the `path` must be an absolute path to the `index.html` file.","severity":"gotcha","affected_versions":">=2.0.0"},{"fix":"Verify that `express-history-api-fallback` is the only fallback middleware in use. Ensure API routes for `POST`, `PUT`, `DELETE` are defined *before* this fallback middleware to guarantee they are handled correctly by your server-side logic.","message":"`express-history-api-fallback` is specifically designed to handle only `GET` and `HEAD` HTTP requests that accept `text/html`. It will not intercept `POST`, `PUT`, `DELETE`, or other non-HTML requests. If your API routes are also returning `index.html` for these methods, another middleware or misconfiguration is likely at fault.","severity":"gotcha","affected_versions":">=2.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure the `path` argument is an absolute file path, or provide the `root` option: `app.use(fallback('index.html', { root: __dirname + '/public' }))`.","cause":"The `path` argument provided to the `fallback` middleware was relative, but the `root` option was not specified in the options object.","error":"TypeError: path must be absolute or specify root to res.sendFile"},{"fix":"Reorder your middleware: `app.use(express.static('public'))` should always come before `app.use(fallback('index.html', { root }))`.","cause":"The `express-history-api-fallback` middleware is placed earlier in the Express middleware chain than the static file serving middleware (e.g., `express.static`). It intercepts requests for static files before they can be served.","error":"My static assets (JS, CSS, images) are not loading, or index.html is served instead of them."},{"fix":"While `express-history-api-fallback` itself doesn't directly ship TypeScript types, if you are using `@types/express-history-api-fallback` (or similar community types), try adjusting the versions of `@types/express` or the history API fallback types to compatible versions. You might need to check the DefinitelyTyped repository for known compatibility issues or install `@ts-ignore` if a quick fix is needed and you're confident in the runtime behavior.","cause":"This specific error often arises when using `@types/express` versions that are incompatible with `@types/connect-history-api-fallback` (a similar but distinct library, though the `express-history-api-fallback` typings might follow a similar pattern). It indicates a mismatch in expected middleware types.","error":"TypeScript error: Argument of type 'RequestHandler<ParamsDictionary, any, any, ParsedQs, Record<string, any>>' is not assignable to parameter of type 'PathParams'."}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":null,"cli_name":""}