Bonjour/Zeroconf Service Discovery for Node.js
bonjour-service is a TypeScript implementation of the Bonjour/Zeroconf protocol, enabling service publishing and discovery on local networks using multicast DNS. It functions as a modern rewrite of the popular `watson/bonjour` package, bringing contemporary TypeScript practices and improved maintainability. Currently stable at version 1.3.0, the package sees periodic updates, often including dependency bumps and minor feature enhancements, as indicated by recent changelogs. Its primary differentiator is providing a reliable, actively maintained, and type-safe solution for mDNS/DNS-SD within the Node.js ecosystem, suitable for applications requiring local network service announcement and detection, such as IoT devices or local development tooling. It offers functionalities to advertise services (e.g., HTTP servers) and browse for existing ones, handling the underlying UDP socket communication and DNS packet parsing.
Common errors
-
Error: bind EADDRINUSE 0.0.0.0:5353
cause Another process is already using the mDNS port (5353). This is common if another mDNS client or server is running.fixEnsure only one instance of `bonjour-service` (or any other mDNS client/server) is running at a time. If running multiple, ensure each `Bonjour` instance has its own unique port configuration if necessary, though mDNS typically operates on 5353. For system-wide conflicts, identify and stop the conflicting process. -
Error: no such host
cause When browsing for services, the `host` property might sometimes appear as 'no such host' if the mDNS resolver couldn't immediately resolve the hostname from the IP address, or if the host went offline before a full resolution could occur.fixThis is often transient. Ensure the target device is online and accessible on the local network. Implement retries or a more robust service tracking logic in your application to handle temporary resolution failures. -
TypeError: Bonjour is not a constructor
cause Attempting to use `require()` with an ES module or incorrect destructuring in CommonJS.fixIf using CommonJS, try `const { Bonjour } = require('bonjour-service');`. If using ES modules, ensure your environment supports `import` syntax and you are using `import { Bonjour } from 'bonjour-service';`.
Warnings
- gotcha Firewall rules can prevent `bonjour-service` from functioning correctly, as it relies on multicast UDP on port 5353. Ensure this port is open for both inbound and outbound traffic if services are not being discovered or published.
- gotcha The `Bonjour` constructor can optionally take an `errorCallback` to handle errors gracefully that would otherwise crash the process, particularly issues with the underlying `multicast-dns` server. It is highly recommended to provide this callback.
- gotcha When publishing services, ensure the `name` is unique on the network for a given `type` and `protocol` to avoid conflicts. Duplicate service names can lead to unpredictable behavior or services not being properly advertised.
- gotcha The `destroy()` method is crucial for releasing network resources. Failing to call `destroy()` on the `Bonjour` instance (and `stop()` on individual services/browsers) can leave UDP sockets open, leading to resource leaks or preventing process exit.
Install
-
npm install bonjour-service -
yarn add bonjour-service -
pnpm add bonjour-service
Imports
- Bonjour
const Bonjour = require('bonjour-service')import { Bonjour } from 'bonjour-service' - Service
import { Service } from 'bonjour-service'import type { Service } from 'bonjour-service' - Options
import type { BonjourOptions } from 'bonjour-service'
Quickstart
import { Bonjour } from 'bonjour-service';
import { createServer } from 'http';
const bonjour = new Bonjour();
const server = createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello from bonjour-service!');
});
const port = 3000;
server.listen(port, () => {
console.log(`HTTP server listening on port ${port}`);
// Advertise an HTTP server on port 3000
const publishedService = bonjour.publish({
name: 'My bonjour-service Web Server',
type: 'http',
port: port,
txt: { version: '1.0', path: '/' }
});
publishedService.on('up', () => {
console.log(`Service '${publishedService.name}' published successfully.`);
});
// Browse for all http services
const browser = bonjour.find({ type: 'http' });
browser.on('up', (service) => {
console.log('Found an HTTP server:', service.name, service.port, service.host);
});
// Stop browsing and unpublish after a delay
setTimeout(() => {
console.log('Stopping services...');
browser.stop();
publishedService.stop();
bonjour.destroy();
server.close(() => console.log('HTTP server closed.'));
}, 15000);
});