DEV Community

giancarlo maci
giancarlo maci

Posted on

MV3 Chrome Extensions: non-obvious issues I wish I knew before building one

If you've ever built a Chrome Extension with Manifest V3,
you've probably hit at least one of these walls.

I did. Multiple times. Here's what I learned the hard way.


1. Service workers don't persist state

This is the biggest mindset shift from MV2.

Any variable you declare in background.js is gone the moment
Chrome decides to kill the service worker — and it will,
unpredictably.

The fix: never store anything in variables. Use chrome.storage
for everything.

// Wrong
let userSettings = {};

// Right
chrome.storage.local.set({ userSettings });
Enter fullscreen mode Exit fullscreen mode

2. Async messaging silently fails without return true

This one cost me hours of debugging.

When you send a message from popup.js to background.js and
expect an async response, you must return true inside the
onMessage listener — otherwise Chrome closes the message
channel before the response arrives.

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.type === 'RUN_ACTION') {
    doSomethingAsync()
      .then(result => sendResponse({ success: true, data: result }));

    return true; // This line is mandatory for async responses
  }
});
Enter fullscreen mode Exit fullscreen mode

No error is thrown if you forget it. The response just never
arrives.


3. chrome.alarms requires explicit permission

You add chrome.alarms to your code. Nothing works. No error.

The reason: you forgot to declare "alarms" in manifest.json.

{
  "permissions": ["storage", "activeTab", "alarms"]
}
Enter fullscreen mode Exit fullscreen mode

Always declare every API you use in permissions. Chrome won't
tell you what's missing.


4. The popup closes on every outside click

This seems obvious in hindsight, but it changes how you design
your UX completely.

Any interaction that requires the user to click outside the
popup — selecting text on a page, switching tabs — closes it
immediately. Design your extension assuming the popup is
temporary, not persistent.


What I built after learning all this

After dealing with these issues on every new project, I put
together a boilerplate that handles all of it out of the box:
popup, background worker, content script, storage and messaging
— all wired together and ready to go.

It's called MG Launch and it's free right now if you want to
try it: macigiancarlo.gumroad.com/l/dckcz


What issues did you run into building MV3 extensions?
Drop them in the comments — would love to compare notes.

Top comments (0)