Getting Started
Relevant source files
The following files were used as context for generating this wiki page:webext-bridge is a library designed to simplify messaging and data synchronization between the different parts of a web extension. It provides a consistent, promise-based API for communication across all extension contexts, such as the background script, content scripts, popups, and more. The library handles the underlying complexity of browser messaging APIs, offering a streamlined developer experience.
This guide provides an overview of the core architecture and fundamental usage patterns to help you integrate webext-bridge into your project. It covers context-specific initialization, sending and receiving messages, and using advanced features like streams for continuous communication.
Sources: README.md:14-16
Core Concepts
Runtime Contexts
A web extension is composed of several distinct JavaScript environments, known as runtime contexts. webext-bridge provides a unified way to communicate between them.
| Context | Description | Source File -
| background | The central script of the extension, often a persistent service worker in Manifest V3. It acts as the message hub. | src/background.ts -
| content-script | A script injected into web pages. It can interact with the DOM and the background script. | src/content-script.ts -
| popup | The script for the browser action's popup UI. | src/popup.ts -
| options | The script for the extension's options page. | src/options.ts -
| devtools | Scripts for the developer tools panel. | src/devtools.ts -
| window | A normal script running in a web page, not a content script. It communicates via the content script. | src/window.ts -
Sources: src/types.ts:4-10
Endpoints
Each runtime context is identified by a unique string called an "Endpoint". This allows messages to be routed to the correct destination. The format is typically context@tabId.frameId.
- Contexts like
background,popup, andoptionsare singletons and are identified just by their name. - Contexts tied to a specific tab, like
content-scriptanddevtools, include the tab ID. - Content scripts can also include a frame ID if they are running within an iframe.
The library provides helper functions parseEndpoint and formatEndpoint to work with these identifier strings.
Sources: src/internal/endpoint.ts:3-16
Architecture Overview
webext-bridge uses a hub-and-spoke architecture with the background script acting as the central message broker. All other contexts (content-script, popup, options, devtools) establish a long-lived, persistent connection to the background script. This connection is designed to be resilient, automatically reconnecting if the background service worker is terminated, which is common in Manifest V3 extensions.
Communication between a regular webpage (window context) and the extension is proxied through the content-script using the standard window.postMessage API.
This diagram illustrates the high-level communication flow between contexts.
This diagram shows the central role of the background script and the different connection methods.
Sources: src/background.ts, src/internal/persistent-port.ts, src/content-script.ts
Basic Usage
Initialization
A critical change in v6.0.0 is that the library no longer auto-detects the runtime context. You must import the bridge from the specific entry point for the context you are working in. This is configured in the project's package.json.
For example:
- In a popup script:
import { sendMessage, onMessage } from 'webext-bridge/popup'; - In a content script:
import { sendMessage, onMessage } from 'webext-bridge/content-script'; - In the background script:
import { onMessage } from 'webext-bridge/background';
This explicit import structure ensures that only the necessary code for a given context is bundled.
Sources: CHANGELOG.md:12-14, package.json:30-53
Sending and Receiving Messages
The core API consists of two main functions: sendMessage and onMessage.
| Function | Description -
| sendMessage | Asynchronously sends a message with a specific ID and data to a destination. It returns a promise that resolves with the response. | src/internal/endpoint-runtime.ts:11-18 -
| onMessage | Registers a callback function to handle incoming messages with a specific ID. The callback can return a value or a promise, which will be sent back as the response. | src/internal/endpoint-runtime.ts:19-22 -
This sequence diagram shows a popup script requesting data from the background script.
This diagram illustrates the asynchronous request/response flow.
Sources: src/internal/endpoint-runtime.ts:11-22, 120-143
Communication with the window context
For a content-script to communicate with a script running on the host page (window context), you must explicitly enable it for security reasons. This is done by defining a shared namespace.
- In
content-script.ts: CallallowWindowMessaging("my-app-namespace"). - In
window.ts: CallsetNamespace("my-app-namespace").
This creates a secure channel using window.postMessage. The namespace prevents conflicts with other extensions or scripts on the same page.
This flow shows the necessary setup for window-to-extension communication.
Sources: src/content-script.ts:40-43, src/window.ts:18-21, src/internal/post-message.ts:28-36
Advanced Feature: Streams
For continuous, bi-directional communication, webext-bridge provides a "Stream" API. This is useful for features like real-time data updates, where a persistent connection is more efficient than repeated sendMessage calls.
openStream(channel, destination): Initiates a stream on a named channel to a specific destination.onOpenStreamChannel(channel, callback): Listens for incoming stream requests on a named channel.
Once a stream is established, both ends can use stream.send(data) to transmit data and stream.onMessage(callback) to receive it.
This sequence diagram demonstrates establishing and using a stream between two contexts.
This diagram shows the lifecycle of a stream from opening to closing.
Sources: src/internal/stream.ts:14-20, 148-160, 162-167
Conclusion
webext-bridge provides a powerful and developer-friendly abstraction over the native web extension messaging APIs. By leveraging a central background script, persistent ports, and a consistent API across all runtime contexts, it simplifies development and handles the complexities of inter-context communication, especially in the context of Manifest V3's service worker lifecycle. The explicit, context-aware imports and features like Streams make it a robust foundation for building complex web extensions.
Sources: README.md:14-16, CHANGELOG.md:4-7