listhen: HTTP Listener and Dev Server
listhen is an elegant HTTP listener for Node.js, designed to streamline local development server setups. It supports various server handlers including Node.js built-in HTTP, Express, and `unjs/h3`, making it highly adaptable for different project types. Currently at version 1.9.1, the package maintains an active release cadence, frequently publishing minor improvements and bug fixes, as evidenced by recent releases such as v1.9.1, v1.9.0, and v1.8.0. Key differentiators include its rich feature set out-of-the-box, such as hot module reloading (HMR) capabilities, static file serving, robust TypeScript support via `unjs/jiti`, and integrated WebSocket support through `unjs/crossws`. It also enhances developer experience with features like automatic port finding (via `get-port-please`), displaying QR codes for public URLs (with `unjs/uqr`), local server tunneling (using `unjs/untun`), clipboard integration for URLs, and simplified HTTPS setup with self-signed certificates. listhen aims to provide a comprehensive, zero-configuration development server experience, abstracting away common setup complexities.
Common errors
-
Address already in use :::3000
cause Another process is currently using the specified port (e.g., 3000).fixSpecify a different port number in the `port` option, or omit the `port` option entirely to allow `listhen` to automatically find an available port using `get-port-please`. -
ERR_REQUIRE_ESM: require() of ES Module ... Not supported.
cause Attempting to use `require()` to import an ES Module package (or a package configured primarily for ESM) in a CommonJS context.fixEnsure your project is configured for ES Modules (add `"type": "module"` to your `package.json` file) and use `import` statements. If you must use CommonJS, verify the package version is fully compatible with CommonJS or consider using a bundler like Webpack/Rollup that handles module interoperability. -
Error: Certificate is not trusted
cause You are using `https: true` with a self-signed certificate, which browsers do not inherently trust.fixFor development, bypass the browser security warning. For production, acquire and configure a valid, trusted SSL certificate by providing `cert` and `key` paths in the `https` option: `{ https: { cert: 'path/to/cert.pem', key: 'path/to/key.pem' } }`.
Warnings
- gotcha The `showURL`, `open`, and `clipboard` options are automatically disabled (`false`) when `listhen` detects a `test` or `production` environment, regardless of explicitly setting them to `true`. This prevents unintended side effects in CI/CD or deployed applications.
- gotcha When `https: true` is used without providing custom certificates, `listhen` generates a self-signed SSL certificate. Most browsers will display a 'not trusted' warning for these certificates, requiring manual acceptance.
- gotcha The `hostname` option defaults to `'0.0.0.0'`, which makes the server accessible from external networks. If you intend for the server to be only accessible from the local machine, you should explicitly set `hostname: 'localhost'` or `hostname: '127.0.0.1'`.
Install
-
npm install listhen -
yarn add listhen -
pnpm add listhen
Imports
- listen
const { listen } = require('listhen')import { listen } from 'listhen' - listenAndWatch
import listenAndWatch from 'listhen'
import { listenAndWatch } from 'listhen' - Listener
import { Listener } from 'listhen'import type { Listener } from 'listhen'
Quickstart
import { createApp, eventHandler } from "h3";
import { listen } from "listhen";
const app = createApp();
app.use(
"/",
eventHandler(() => "Hello world from listhen and h3!")
);
async function startServer() {
const listener = await listen(app, {
port: process.env.PORT ? parseInt(process.env.PORT) : 3000, // Use process.env.PORT or fallback to 3000
hostname: process.env.HOST || "0.0.0.0",
clipboard: true, // Copy URL to clipboard in dev
open: true, // Open in browser in dev
showURL: true, // Show URL in console
https: false // Set to true for self-signed HTTPS in dev
});
console.log(`Server listening on ${listener.url}`);
// Graceful shutdown on common signals
process.on('SIGINT', () => { listener.close(); console.log('Server gracefully shutting down...'); });
process.on('SIGTERM', () => { listener.close(); console.log('Server gracefully shutting down...'); });
}
startServer();