Tiny LiveReload Fork
tiny-lr-fork is an actively maintained fork of the original `tiny-lr` package, which had become unmaintained. It provides a lightweight, background-friendly LiveReload server implementation for development workflows. Unlike the original, this fork addresses lingering issues, incorporates community contributions, and includes security patches. Key differentiators include quieter operation (reduced `console.log` output), proper handling of WSS for `livereload.js` over HTTPS, and normalized Windows file paths. The server exposes a simple HTTP/WebSocket API that build tools (like Grunt, or custom scripts) can use to notify connected LiveReload clients (browser extensions or injected scripts) about file changes. It does not perform file watching itself, requiring external integration for detecting changes. The current stable version, as per the changelog, is 2.0.0, with a release cadence driven by bug fixes and necessary updates rather than a fixed schedule.
Common errors
-
Error: listen EADDRINUSE: address already in use :::35729
cause Another process, or a previous instance of your `tiny-lr-fork` server, is already listening on the specified port (default 35729).fixStop the conflicting process, or configure `tiny-lr-fork` to listen on a different port using the `-p` or `--port` command line option, or by passing a `port` option to `tinylr().listen(port, ...)`. -
WebSocket connection to 'ws://localhost:35729/livereload' failed: Error during WebSocket handshake: Unexpected response code: 404
cause The `tiny-lr-fork` server is either not running, or its middleware is not correctly mounted in your application stack, leading to the `/livereload` path not being handled.fixEnsure your `tiny-lr-fork` server is running. If using it as middleware, verify `app.use(lrserver.middleware({ app: app }));` is correctly placed in your Connect/Express application and the `app` object is the same as the one listening on the port. -
TypeError: app.use() requires a middleware function but got a undefined
cause This typically occurs when `express.bodyParser()` or `express.query()` are referenced as middleware in older examples, but are either not imported or are deprecated in your version of Express.fixFor modern Express (4.x+), use `app.use(express.json());` and `app.use(express.urlencoded({ extended: true }));` to handle body and query parsing before the `tiny-lr-fork` middleware.
Warnings
- breaking Version 2.0.0 of tiny-lr-fork, alongside its dependency `livereload-js`, has officially dropped support for Internet Explorer versions 6 through 9. Projects targeting these legacy browsers will experience issues.
- gotcha When integrating `tiny-lr` as Connect/Express middleware, it requires query and body parsing middleware to be registered *prior* in the stack for POST requests to `/changed` to work correctly. For modern Express, `express.json()` and `express.urlencoded()` are needed.
- gotcha The LiveReload browser extensions (Chrome, Firefox, Safari) by default connect to port `35729`. If you configure `tiny-lr-fork` to listen on a different port, the browser extension will not automatically connect. You will need to manually configure the extension or inject the `livereload.js` script with the correct port.
- gotcha `tiny-lr-fork` is a server that *receives* reload notifications and broadcasts them. It does not include built-in file watching capabilities. You must use an external build tool (e.g., Gulp, Webpack, or a simple `fs.watch` script) to detect file changes and then notify `tiny-lr-fork`.
- deprecated Previous versions of `tiny-lr-fork` (and its original `tiny-lr` predecessor) had vulnerabilities in the `debug` and `qs` dependencies. While these have been patched in recent releases, it's crucial to stay updated.
Install
-
npm install tiny-lr-fork -
yarn add tiny-lr-fork -
pnpm add tiny-lr-fork
Imports
- tinylr
import tinylr from 'tiny-lr';
const tinylr = require('tiny-lr'); - tinylr.Server
import { Server as LiveReloadServer } from 'tiny-lr';const LiveReloadServer = require('tiny-lr').Server; - tinylr.middleware
import { middleware as lrMiddleware } from 'tiny-lr';const lrMiddleware = require('tiny-lr').middleware;
Quickstart
const tinylr = require('tiny-lr');
const path = require('path');
const express = require('express');
const PORT = 35729; // Standard LiveReload port for browser extensions
const app = express();
// Initialize tiny-lr server
const lrserver = tinylr();
// Listen for specific requests on the tiny-lr server (optional)
lrserver.on('GET /custom-status', (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('tiny-lr server is running and custom route works!');
});
// Integrate tiny-lr middleware with Express
// In modern Express, query parsing is built-in, but body-parser might still be needed.
app.use(express.json()); // For POST requests with JSON body
app.use(express.urlencoded({ extended: true })); // For URL-encoded bodies
app.use(lrserver.middleware({ app: app })); // Bind tiny-lr routes to the Express app
// Serve static files (e.g., your project's root)
app.use(express.static(path.resolve('./')));
// Start the Express app and tiny-lr server
app.listen(PORT, function() {
console.log(`Express app and tiny-lr server listening on port ${PORT}`);
console.log('Use `curl http://localhost:35729/changed?files=index.html` to trigger reloads.');
console.log('Or `curl -X POST http://localhost:35729/changed -d "{\"files\":[\"style.css\"]}"`');
});
// Example of how to trigger a reload programmatically
// setTimeout(() => {
// lrserver.changed({ body: { files: ['index.html'] } });
// console.log('Triggered a reload after 5 seconds.');
// }, 5000);