express, http-server, live-server, and serve are all tools used to serve web content in Node.js, but they target different stages of the development lifecycle and production needs. express is a full-featured web application framework that allows developers to build complex APIs, handle routing logic, and manage middleware for production-grade applications. http-server is a zero-configuration command-line utility designed to quickly serve static files for testing or simple hosting without any build steps. live-server extends static serving by adding automatic browser reloading and CSS injection, making it ideal for rapid frontend prototyping. serve is a modern, robust static file server built by Vercel that offers a balance of simplicity for local development and powerful configuration options for production deployment of static sites.
When working with JavaScript, you often need to serve files or build an API. While all four tools—express, http-server, live-server, and serve—run on Node.js, they solve very different problems. Some are built for quick local testing, others for active development with hot reloading, and some for full-scale production applications. Let's break down how they work and when to use each one.
The biggest difference lies in what these tools are designed to do. express is a framework. It gives you the building blocks to create a web server from scratch, including routing, middleware, and request handling. The other three are utilities designed to serve static files immediately.
express requires you to define how the server behaves. You must explicitly tell it which port to listen on and how to handle requests.
// express: Manual setup required
const express = require('express');
const app = express();
const port = 3000;
app.use(express.static('public'));
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
http-server, live-server, and serve work out of the box. You usually run them directly from the terminal without writing any JavaScript code.
# http-server: Run immediately in folder
npx http-server
# live-server: Run with auto-reload
npx live-server
# serve: Run with defaults
npx serve
When you are writing code, you want to see changes instantly. This is where live-server shines. It watches your files and forces the browser to refresh whenever you save. serve and http-server generally do not do this by default.
live-server injects a small script into your HTML to handle reloading. It can even update CSS without a full page refresh.
# live-server: Watches files and reloads browser
npx live-server ./src
# Output: Serving "./src" at http://127.0.0.1:8080
http-server serves files but stays static. If you change a file, you must manually refresh the browser.
# http-server: No auto-reload
npx http-server ./dist
# You must press F5 in the browser to see changes
serve focuses on performance and standards. It does not include live reloading in its core package. Developers often pair it with a bundler like Vite or Webpack for hot module replacement.
# serve: Static serving only
npx serve ./build
# No automatic browser refresh on file change
express does not have live reloading built-in. You need to add third-party middleware like nodemon (for the server) and browser sync tools to get similar behavior.
// express: Requires extra setup for reloading
// Typically run with: nodemon server.js
const app = require('express')();
// No native file watching for client-side updates
As projects grow, you need more control over headers, redirects, and single-page application (SPA) routing. express and serve offer strong configuration options, while http-server and live-server are more limited.
serve uses a serve.json file for configuration. This is great for defining rewrites for SPAs (like React Router) without writing code.
// serve.json
{
"rewrites": [
{ "source": "**", "destination": "/index.html" }
],
"headers": [
{
"source": "**/*.js",
"headers": [{ "key": "Cache-Control", "value": "public, max-age=31536000" }]
}
]
}
express handles configuration entirely in code. This gives you unlimited flexibility to create custom logic, conditional redirects, or dynamic middleware chains.
// express: Custom SPA fallback in code
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'index.html'));
});
app.use((req, res, next) => {
res.setHeader('Cache-Control', 'public, max-age=31536000');
next();
});
http-server relies on command-line flags. It supports basic CORS and caching headers but lacks complex rewrite rules.
# http-server: CLI flags only
npx http-server -c-1 --cors
# -c-1 disables caching, --cors enables Cross-Origin Resource Sharing
live-server also uses CLI flags or a simple config file, but it is primarily tuned for development. It lacks the robust production headers found in serve.
# live-server: CLI flags
npx live-server --port=8080 --no-browser
Not all tools are safe or efficient for production. express and serve are designed to handle real traffic. http-server and live-server are meant for development and testing only.
express is the industry standard for production Node.js apps. It supports clustering, error handling, and security middleware.
// express: Production error handling
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
serve is optimized for production static hosting. It handles compression (gzip/brotli) and supports HTTPS setup easily.
# serve: Production mode with compression
npx serve --prod
# Enables gzip and brotli compression automatically
http-server and live-server should NOT be used in production. They lack advanced security features, performance optimizations, and process management required for public-facing services.
# WARNING: Do not use in production
npx http-server
npx live-server
# These are for local development and testing only
It is critical to note that live-server is deprecated. The original repository is no longer maintained, and it has known security vulnerabilities in its dependencies. For new projects requiring live reloading, developers should use modern build tools (like Vite, Parcel, or Webpack Dev Server) instead of relying on live-server.
# Avoid using live-server in new projects
# npm install live-server <-- Not recommended
| Feature | express | http-server | live-server | serve |
|---|---|---|---|---|
| Type | Framework | CLI Utility | CLI Utility | CLI Utility |
| Setup | Code required | Zero-config | Zero-config | Zero-config / JSON |
| Live Reload | No (needs plugins) | No | Yes | No |
| SPA Support | Custom Code | No | No | Config File |
| Production | Excellent | ❌ No | ❌ No (Deprecated) | Excellent |
| Best For | APIs & Dynamic Apps | Quick Tests | Legacy Prototyping | Static Sites |
Choosing the right tool depends on your current goal. If you are building a backend API or a complex server-rendered app, express is the only choice here that fits. It gives you full control but requires more code.
If you just built your React or Vue app and need to test the production build locally, serve is the modern standard. It is secure, fast, and handles SPA routing with a simple config file.
For quick checks—like opening an HTML file to verify a layout—http-server is still useful. However, avoid live-server for new work. Since it is deprecated, switch to dedicated dev servers provided by modern bundlers for a safer and faster development experience.
Choose express when you need to build a custom backend API, handle complex routing logic, or integrate middleware for authentication and data processing. It is the standard choice for production applications requiring dynamic server-side rendering or REST/GraphQL endpoints, though it requires more setup than static servers.
Choose http-server for quick, one-off tasks like verifying a build output, testing static HTML files locally, or running a simple file server in CI/CD pipelines. It is best suited for scenarios where you need a lightweight, zero-config solution and do not require live reloading or advanced security headers.
Choose live-server during the active development phase of a frontend project where you need immediate visual feedback. Its ability to inject CSS changes and reload the browser automatically saves time when tweaking styles or HTML, making it superior to basic static servers for iterative design work.
Choose serve when you need a reliable, production-ready static file server that is easy to configure via a JSON file. It is ideal for deploying Single Page Applications (SPAs) or static sites where you need features like custom ports, compression, and SPA routing fallbacks without writing custom server code.
Fast, unopinionated, minimalist web framework for Node.js.
This project has a Code of Conduct.
import express from 'express'
const app = express()
app.get('/', (req, res) => {
res.send('Hello World')
})
app.listen(3000, () => {
console.log('Server is running on http://localhost:3000')
})
This is a Node.js module available through the npm registry.
Before installing, download and install Node.js. Node.js 18 or higher is required.
If this is a brand new project, make sure to create a package.json first with
the npm init command.
Installation is done using the
npm install command:
npm install express
Follow our installing guide for more information.
PROTIP Be sure to read the migration guide to v5
The quickest way to get started with express is to utilize the executable express(1) to generate an application as shown below:
Install the executable. The executable's major version will match Express's:
npm install -g express-generator@4
Create the app:
express /tmp/foo && cd /tmp/foo
Install dependencies:
npm install
Start the server:
npm start
View the website at: http://localhost:3000
The Express philosophy is to provide small, robust tooling for HTTP servers, making it a great solution for single page applications, websites, hybrids, or public HTTP APIs.
Express does not force you to use any specific ORM or template engine. With support for over 14 template engines via @ladjs/consolidate, you can quickly craft your perfect framework.
To view the examples, clone the Express repository:
git clone https://github.com/expressjs/express.git --depth 1 && cd express
Then install the dependencies:
npm install
Then run whichever example you want:
node examples/content-negotiation
The Express.js project welcomes all constructive contributions. Contributions take many forms, from code for bug fixes and enhancements, to additions and fixes to documentation, additional tests, triaging incoming pull requests and issues, and more!
See the Contributing Guide for more technical details on contributing.
If you discover a security vulnerability in Express, please see Security Policies and Procedures.
To run the test suite, first install the dependencies:
npm install
Then run npm test:
npm test
For information about the governance of the express.js project, see GOVERNANCE.md.
The original author of Express is TJ Holowaychuk