PlasmoHQ / plasmo

🧩 The Browser Extension Framework
https://www.plasmo.com
MIT License
10.14k stars 350 forks source link

[BUG] with-messaging ports example doesn't work #848

Open robertsamarji opened 8 months ago

robertsamarji commented 8 months ago

What happened?

I have the code below, which closely mimics the with-messaging Plasmo example:

// ~/background/messages/message-handler.ts

import { getPort } from "@plasmohq/messaging/background"

import type { PlasmoMessaging } from "@plasmohq/messaging"

const handler: PlasmoMessaging.MessageHandler = async (req, res) => {
  const port = getPort("test")
  port.postMessage("Test message")
  res.send({ success: true })
}

export default handler
// ~/background/ports/test.ts

import type { PlasmoMessaging } from "@plasmohq/messaging"

const handler: PlasmoMessaging.PortHandler = async (req, res) => {
  console.log({ req })
  res.send(req)
}

export default handler

When message-handler.ts is called by an external webpage sending a message to the extension via relayMessage in a content script, instead of the message handler sending a message "Test message" to the port, the service worker logs the following error:

background.cjs:1 Uncaught (in promise) Error: Port test not found
    at x (background.cjs:1:791)
    at handler (message-handler.ts:7:20)
    ...
    await in handler (async)
    anonymous            @ messaging.ts:177

Version

Latest

What OS are you seeing the problem on?

MacOSX

What browsers are you seeing the problem on?

Chrome

Relevant log output

No response

(OPTIONAL) Contribution

Code of Conduct

Acorn221 commented 8 months ago

Hi there, I'd recommend you do a little more reading into the messaging API in the plasmo docs, or ask the AI bot Pallas on the discord which has also helped me out loads. From the limited code that I can see though, I can say that the error you are currently running into is from having your port handler under ~/background/messages/ports/test.ts instead of ~/background/ports/test.ts, as having the port handler under the wrong directory would cause plasmo not to run that code as a port.

robertsamarji commented 8 months ago

Hey @Acorn221, thank you for your message, I will check out the discord - thanks for the tip!

Good spot, I realised that was actually a copy/paste error, my port hander is in fact under ~/background/ports/test.ts - my other ports are working. I've updated my comment to reflect that. If you have any other ideas as to why this is erroring, please do let me know!

Acorn221 commented 8 months ago

Ahh I see, I'm also pretty sure that the chrome ports API is not designed for you to communicate from within the background service worker, to the background service worker. You might be better off by registering an event target under background/index.ts and importing it into the message handler, firing off an event from that message handler, then just adding some code in that monitors that EventTarget instance for the event that you fire off. So instead of having your test.ts port, you would just have extra code running in background/index.ts that looked like

const target = new EventTarget();

target.addEventListener('test', () => {
  console.log("I am an event that has been triggered");
});
export { target };

Then under your message handler, you'd have something like

import { target } from '~/background';

import type { PlasmoMessaging } from "@plasmohq/messaging"

const handler: PlasmoMessaging.MessageHandler = async (req, res) => {
  const event = new Event('test');
  target.dispatchEvent(event);
  res.send({ success: true })
}

export default handler

I hope this helps! Let me know if you run into any issues with it.

robertsamarji commented 8 months ago

Hey @Acorn221, this is fantastic. Wouldn't have thought of this. Thank you for your help. Will try this in the morning and let you know how it goes.

robertsamarji commented 8 months ago

Hey @Acorn221 this worked fantastically, thank you.

I didn't manage to get my initial code, which follows the with-messaging Plasmo example, to work. However your workaround worked great.