A type-safe RPC implementation for Chrome Extensions, supporting communication between Background, Content Scripts, Web Pages, and extension runtime pages such as Popup and Sidepanel.
npm install crx-rpcOr using other package managers:
# pnpm
pnpm add crx-rpc
# yarn
yarn add crx-rpc- Type-safe: Built with TypeScript for full type safety and IntelliSense support.
- Flexible: Supports various communication paths within a Chrome Extension.
- Native request-reply: Uses Chrome's native
sendMessage/sendResponseflow for RPC calls. - Automatic Environment Detection: Host APIs automatically detect background vs content runtime.
- Single client API: One client entry point for background, content, and web page initiated calls.
- Web request relay: Web pages use custom events to call content services directly and relay background calls through the content script.
import { createIdentifier } from 'crx-rpc'
export interface IMathService {
add(a: number, b: number): Promise<number>
}
export const IMathService = createIdentifier<IMathService>('math-service', 'background')import { createHost } from 'crx-rpc'
import { IMathService } from './api'
class MathService implements IMathService {
async add(a: number, b: number) {
return a + b
}
}
// Automatically detects environment (background/content)
const host = createHost()
host.register(IMathService, new MathService())import { createClient } from 'crx-rpc'
import { IMathService } from './api'
// Works in extension pages and injected web pages
const client = createClient()
// Call background service
const mathService = client.createRPCService(IMathService)
const result = await mathService.add(1, 2) // 3
// Call content service (provide tabId)
const contentService = client.createRPCService(IContentService, { tabId: 123 })
await contentService.doSomething()- Type-safe: Built with TypeScript.
- Flexible: Supports various communication paths within a Chrome Extension.
- Request-reply: Uses one native message round trip per RPC call.
The library facilitates communication between different parts of a Chrome Extension.
Services can be hosted in two locations:
- Background: Hosted in the background service worker. Handles requests from Content Scripts and Popup/Sidepanel.
- Content Script: Hosted in the content script. Handles requests from Background and Popup/Sidepanel.
| Caller | Target | Usage |
|---|---|---|
| Content Script | Background | client.createRPCService(IBackgroundService) |
| Popup/Sidepanel | Background | client.createRPCService(IBackgroundService) |
| Background | Content Script | client.createRPCService(IContentService, { tabId }) |
| Popup/Sidepanel | Content Script | client.createRPCService(IContentService, { tabId }) |
| Web Page | Content Script | client.createRPCService(IContentService) |
| Web Page | Background | Relayed through content with client.createRPCService(IBackgroundService) |
Note: When
createClient()runs in a web page, it usesCustomEventrequest/response relays. Background calls are forwarded by the content script.
createHost(log?: boolean): Creates a unified RPC host that auto-detects background vs contentUnifiedRPCHost: Unified host class built on native Chrome request-reply messagingcreateClient(): Creates a unified RPC client for extension runtime and injected web page contextsUnifiedRPCClient: Unified client class with dynamictabIdsupport in extension contexts and request-relay support in web pagesBaseService: Base class for service implementations with a sharedgetService()helpercreatePlaywrightBridge(): Creates a Playwright RPC bridge for background/content mutual callsPlaywrightRPCBridge#createBackgroundHost(log?: boolean): Creates a background host in Node runtimePlaywrightRPCBridge#createContentHost(page, targetId, log?: boolean): Creates a content host bound to a real Playwright pagePlaywrightPageContentHost#register(identifier, serviceOrFactory): Registers either a page-evaluated factory or aPlaywrightPageServiceinstance with sharedgetService()supportPlaywrightRPCBridge#createClient(options): Creates a client with{ from, defaultTargetId? }