Following up on Nick Cardosos's response, with the advent of module scripts, v3 manifest, etc...
Enable the background to be modular (manifest.json):
"background": {
"service_worker": "background/index.mjs",
"type": "module"
},
Enable access to content modules (manifest.json):
"web_accessible_resources": [
{
"resources": [
"manifest.json",
"src/index.mjs",
],
...
}
],
Define the root content module:
"content_scripts": [
{
"js": [ "extension.js" ],
...
}
],
Inject a module into the client (from extension.js):
document.querySelector('head').appendChild(
Object.assign(document.createElement('script'), {
type: 'module',
src: chrome.runtime.getURL('./src/index.mjs'),
}),
);
From the module, get the extension ID (src/index.mjs):
const extensionId = new URL(import.meta.url).hostname
Send a message (./src/index.mjs or any other module):
export const sendMessage = (message) => new Promise((resolve, reject) => {
try {
chrome.runtime.sendMessage(
extensionId,
message,
(response) => {
if (response?.isError === true) {
reject(Object.assign(
new Error(response.message),
response,
));
} else {
resolve(response);
}
},
);
} catch (e) {
reject(e);
}
});
/* ... */
const responsePayload = await sendMessage(messagePayload);
Receive a message and send a response (./background/index.mjs):
export const onMessageExternal = (listener) => {
chrome.runtime.onMessageExternal.addListener(
async (messagePayload, sender, sendResponse) => {
try {
const response = await listener(messagePayload, sender);
sendResponse(response);
} catch (e) {
const { message, stack, name } = e;
// How you wrap errors is up to you, but the client
// and server must agree on the contract.
sendResponse({
isError: true,
message,
stack,
name,
});
}
},
);
};
/* ... */
onMessageExternal(async (messagePayload, sender) => {
console.log(messagePayload, sender);
return handleMessage(messagePayload);
});
It's important to note that if you do not call sendResponse
, the client's promise will never resolve. That's why I wrapped sendMessage
and onMessageExternal
so that they'd deal appropriately.