Minimal, framework-agnostic EventBus for UI signaling and cross-runtime communication
npm install eventbus-z !Downloads
---
A minimal, framework-agnostic EventBus for frontend applications.
What it is
- Simple emit / listen event bus
- No shared state, no side effects, no magic
- Designed for UI-level communication
What it is NOT
- Not a state manager
- Not a data pipeline
- Not a middleware system
---
- ✅ Simple API (emit / on / off)
- ✅ Typed events (TypeScript, optional)
- ✅ Global shared bus (safe window.top + globalThis)
- ✅ Multi-instance (isolated buses)
- ✅ Micro-frontend & iframe friendly
- ✅ Works with React / Vue / Angular / Vanilla JS
- ✅ Zero dependencies
---
``bash`
npm install eventbus-z
---
`ts
import EventBus from "eventbus-z";
// import { $on, $off, $emit } from "eventbus-z";
`
---
`ts
EventBus.$on("PING", () => {
console.log("pong");
});
EventBus.$emit("PING");
`
---
`tsx
import React from "react";
import EventBus from "eventbus-z";
// Note: callback reference must be stable
export default function App() {
React.useEffect(() => {
const handler = (value: number) => {
alert(value);
};
EventBus.$on("ALERT", handler);
return () => EventBus.$off("ALERT", handler);
}, []);
return (
);
}
`
---
`tsx
import React from "react";
import { $on, $off } from "eventbus-z";
export function useEventBus(
name: string,
callback: (...args: any[]) => void
) {
React.useEffect(() => {
$on(name, callback);
return () => $off(name, callback);
}, [name, callback]);
}
`
---
`ts
// Type-safe at compile time, zero runtime cost
import { createTypedEventBus } from "eventbus-z";
type AppEvents = {
login: [userId: string];
logout: [];
};
const bus = createTypedEventBus
bus.$on("login", id => {
console.log(id); // string
});
bus.$emit("login", "user-1");
// bus.$emit("login", 123); // ❌ Type error
`
---
Useful for:
- Tests
- Micro-frontends
- Embedded apps
`ts
import { createEventBus } from "eventbus-z";
const busA = createEventBus();
const busB = createEventBus();
busA.$on("PING", () => console.log("A"));
busB.$emit("PING"); // nothing happens
`
---
#### Cached
`ts
// cache is user-land utility, not from eventbus-z
const getUser = cached(async (id) => fetchUser(id))
// event
EventBus.$emit("USER_REQUEST", id)
// listener
EventBus.$on("USER_REQUEST", async (id) => {
const user = await getUser(id)
render(user)
})
`
| Method | Description |
|----------------------------------------------------------|-------------|
| $emit(name, ...args) | Emit event |$once(name, callback)
| | Listen once |$on(name, callback)
| | Single listener (unique callback) |$onMultiple(name, callback)
| | Allow multiple listeners |$onCached(name, callback, time?)
| | Single listener with cache |$onCachedMultiple(name, callback, time?)
| | Multi listeners with cache |$off(name, callback)
| | Remove listener |$offAll(name)
| | Remove all listeners |$clearEventAcrossScopes(name)
| | Remove event name from all scopes & caches |
---
| Method | Description |
|-----------------------------------------------------------|------------|
| $scopeEmit(name, scope, ...args) | Emit event in scope |$scopeOnce(name, scope, callback)
| | Listen once in scope |$scopeOn(name, scope, callback)
| . | Single listener in scope |$scopeOnMultiple(name, scope, callback)
| | Multiple listeners |$scopeOnCached(name, scope, callback, time?)
| | Cached listener |$scopeOnCachedMultiple(name, scope, callback, time?)
| . | Cached multi |$scopeOff(name, scope, callback?)
| . | Remove listener |$scopeOffAll(name, scope)
| . | Remove all listeners |
---
- EventBus is synchronous
- No internal queue, no async scheduling
- Deterministic execution order
- Designed for UI signaling, not data flow
If you need:
- state → use a store
- async pipelines → use effects
- business logic → keep it outside EventBus
---
eventbus-z is intentionally minimal.
It does NOT provide:
- State management
- Async pipelines or queues
- Middleware or plugins
- Event replay / history
- Rx / stream semantics
---
| Feature / Library | eventbus-z | mitt |
| ---------------------------- | -------------------------------- | -------------------- |
| Core purpose | UI signaling / infra event bus | Minimal pub/sub |
| Emit / listen | ✅ | ✅ |
| Once listener | ✅ Built-in | ❌ Manual |
| Multiple listeners control | ✅ (single / multiple) | ❌ |timeCached
| Cached / throttled emit | ✅ () | ❌ |scopeName
| Scoped events | ✅ () | ❌ |window.top
| Global + isolated instances | ✅ | ❌ (single instance) |
| micro-frontend / iframe safe | ✅ ( / globalThis) | ❌ |createEventBus`) | ⚠️ Manual |
| Typed Event Map (TS) | ✅ Supported | ⚠️ Limited |
| Test isolation | ✅ (
| Middleware / plugins | ❌ (by design) | ❌ |
| Bundle size | Small | Smaller |
| Learning curve | Low | Very low |
---
MIT