Pushstate Server
Pushstate Server is a minimalistic static file server designed to work seamlessly with HTML5 Pushstate, a browser API for manipulating browser history. It addresses the common single-page application (SPA) routing problem where direct access to a deep link (e.g., `/users/123`) would result in a 404 error because no physical file exists at that path on the server. Instead, this server is configured to return the `index.html` file for any route that does not directly map to a static asset. Conversely, requests for actual static files (e.g., `/assets/logo.png`) are served directly. The package is currently at version 3.1.0. Its release cadence appears to be very slow or effectively ceased, with the last publish on npm dating back over seven years to February 12, 2019. Key differentiators include its simple configuration for HTML5 Pushstate routing, supporting multiple directories for serving static assets, and binding to specific hosts or ports. It remains a lightweight solution for basic SPA hosting needs, though its lack of recent updates may pose compatibility or security considerations for modern development workflows.
Common errors
-
Error: Cannot find module 'pushstate-server'
cause The 'pushstate-server' package has not been installed or is not accessible in the current project environment.fixRun `npm install pushstate-server` or `npm install -g pushstate-server` if using the global CLI. Ensure the package is listed in `package.json` dependencies if it's a project-specific dependency. -
EADDRINUSE: address already in use :::3000
cause The specified port (e.g., 3000) is already being used by another process on your system.fixChange the `port` option in your server configuration to an available port, or terminate the process currently using the desired port. You can often use `process.env.PORT` to allow dynamic port assignment. -
Client-side `history.pushState()` or `history.replaceState()` does not correctly load content after browser refresh.
cause While `pushstate-server` ensures non-static routes return `index.html`, the client-side JavaScript might not correctly re-initialize the application state or render the appropriate view when the browser performs a full refresh on a deep link. This is a common issue with HTML5 Pushstate SPAs if the client-side rendering logic isn't robust enough to handle initial load on arbitrary URLs.fixEnsure your single-page application's client-side router is configured to read the current URL path on initial load and render the corresponding component. The `pushstate-server` provides the necessary `index.html`, but the SPA framework must take over routing from there.
Warnings
- gotcha The package has not been updated in over seven years (last published Feb 12, 2019). It is a CommonJS module and does not natively support ES Modules (ESM) syntax, which is the standard for modern JavaScript development. Projects using ESM will need to use `require()` or a transpilation layer.
- gotcha As a static file server, `pushstate-server` relies on proper configuration to prevent security vulnerabilities. Serving sensitive files or directories that contain user-uploaded content without proper validation could lead to exposure or path traversal attacks.
- gotcha When using the `file` option to specify a custom entry point (e.g., `app.html` instead of `index.html`), ensure that the client-side routing logic correctly references this file for non-static routes. Misconfiguration can lead to blank pages or incorrect content being served.
Install
-
npm install pushstate-server -
yarn add pushstate-server -
pnpm add pushstate-server
Imports
- server
import server from 'pushstate-server';
const server = require('pushstate-server'); - start
import { start } from 'pushstate-server';const server = require('pushstate-server'); server.start({ port: 3000, directory: './public' });
Quickstart
const server = require('pushstate-server');
// Start a server for a single directory
server.start({
port: process.env.PORT ?? 3000,
directory: './public'
});
console.log(`Server started on port ${process.env.PORT ?? 3000} serving './public'.`);
console.log('Access your single-page app at http://localhost:3000');
console.log('e.g., http://localhost:3000/some/pushstate/route will serve index.html');
// Or for multiple directories
// server.start({
// port: process.env.ANOTHER_PORT ?? 4200,
// directories: ['./dist', './node_modules']
// });