Tiny WebSocket Middleware
raw JSON → 1.0.0 verified Thu Apr 23 auth: no javascript
tinyws is a lightweight, framework-agnostic WebSocket middleware for Node.js, built upon the popular `ws` library. It enables WebSocket capabilities for HTTP servers, integrating seamlessly with frameworks like tinyhttp, Express, and Polka by exposing a `req.ws()` method. The current stable version is 1.0.0, as of April 2026. This package distinguishes itself from alternatives like `express-ws` by being actively maintained, providing first-class TypeScript support, being pure ESM, and boasting a minimal footprint (under 500B). Its primary release cadence appears to be focused on stability and maintenance rather than rapid feature additions, making it a reliable choice for adding WebSockets to modern Node.js applications.
Common errors
error Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'ws' imported from tinyws ↓
cause The `ws` package, a peer dependency, has not been installed.
fix
Run
npm install ws or pnpm i ws to add the required WebSocket library. error TypeError: Cannot read properties of undefined (reading 'ws') ↓
cause The `tinyws` middleware was not correctly initialized with your application and HTTP server, or the request path does not match a configured WebSocket path.
fix
Ensure
tinyws(app, server, { paths: '/your-ws-path' }); is called after your HTTP server is created, and that the client is connecting to one of the specified paths. error TypeError: req.ws is not a function ↓
cause The `tinyws` middleware might be applied but `req.ws` is not correctly typed or the `req.ws` property is not being awaited.
fix
Ensure your
Request type is augmented with TinyWSRequest (e.g., App<Request & TinyWSRequest>) and that you await req.ws() to get the WebSocket instance. Warnings
breaking tinyws is a pure ESM package. Applications that are strictly CommonJS (CJS) will need to convert to ESM or use dynamic `import()` for tinyws to function correctly. Direct `require()` calls will result in an error. ↓
fix Ensure your project is configured for ESM (e.g., `"type": "module"` in `package.json`). For mixed CJS/ESM projects, use `import()` within an `async` function: `const { tinyws } = await import('tinyws');`
gotcha It is crucial to install the `ws` package alongside `tinyws`, as `ws` is a peer dependency and not bundled. Forgetting `ws` will lead to runtime errors when tinyws attempts to use it. ↓
fix Run `npm install ws` or `pnpm i ws` in your project directory.
gotcha When integrating `tinyws` with an HTTP server, ensure the `tinyws` initialization function is called *after* the HTTP server is created and passed the `app` instance and the `server` object. Calling it too early or with incorrect arguments will prevent WebSocket upgrades from functioning. ↓
fix Follow the pattern `const server = app.listen(PORT); tinyws(app, server);` ensuring both `app` and the raw `http.Server` instance are provided.
gotcha Unlike some other middleware, `tinyws` exposes the WebSocket functionality via a `req.ws()` *function* that returns a Promise for the WebSocket instance. Developers must `await` this call and check for `req.ws`'s existence to correctly handle WebSocket connections. ↓
fix Always use `if (req.ws) { const ws = await req.ws(); /* ... */ }` within your route handler to properly establish and interact with the WebSocket.
Install
npm install tinyws yarn add tinyws pnpm add tinyws Imports
- tinyws wrong
const tinyws = require('tinyws')correctimport { tinyws } from 'tinyws' - TinyWSRequest wrong
import type { TinyWSRequest } from 'tinyws'correctimport { TinyWSRequest } from 'tinyws' - App wrong
import { App } from 'express'correctimport { App, Request } from '@tinyhttp/app'
Quickstart
import { App, Request } from '@tinyhttp/app';
import { tinyws, TinyWSRequest } from 'tinyws';
import { WebSocket } from 'ws'; // For type inference if needed
const app = new App<Request & TinyWSRequest>();
app.use('/ws', async (req, res) => {
if (req.ws) {
const ws: WebSocket = await req.ws();
ws.on('message', (message) => {
console.log(`Received: ${message}`);
ws.send(`Echo: ${message}`);
});
ws.on('close', () => console.log('WebSocket closed.'));
ws.send('Hello from tinyws server!');
} else {
res.send('Hello from HTTP endpoint! This is not a WebSocket connection.');
}
});
const server = app.listen(3000, () => {
console.log('HTTP/WebSocket server listening on port 3000');
});
tinyws(app, server, { paths: '/ws' });
// To test, run:
// node -e "const WebSocket = require('ws'); const ws = new WebSocket('ws://localhost:3000/ws'); ws.onopen = () => ws.send('Test message'); ws.onmessage = (event) => console.log(event.data);"