Migrating to MV3 and what I didn't learn from it

Full article

Well, that was fun. And by fun, I mean frustrating and pointless. So. Not fun.

Over the summer I wrote about Google's forced manifest v3 update, and whether I felt like figuring it out. I didn't. But with only about 6 weeks left (actually, looks like things got pushed out 6 months since the original article), I figured it was time to make a decision on my own addons, one way or the other. Part of me wanted to just say forget it, but then I looked back at the reviews, and how Hide Comments Everywhere has helped some people, and I decided to give it another go.

To briefly recap, Google is spearheading a change to the way browser extensions are written, claiming it increases security and privacy. Ironically, it'll be deterimental to the way privacy extensions like Ghostery and uBlock Origin work, and the Electronic Frontier Foundation is calling it out as harmful. Since nearly all the major browsers are built on top of Chromium however, we're all along for the ride.

It's a nuisance for everyone too, because every addon developer now needs to spend time figuring out how MV3 works, what changes are required, and make those changes before June 2023 when Google unlists MV2 addons from their store. Don't be shocked if some of your favorite browser addons simply vanish next summer.

Firefox, which isn't built on Chromium, is attempting to support both and will begin accepting MV3 addons in just a couple days, although they aren't requiring anyone to adopt the change. I wonder how manageable that will be in the long run?

Before tackling the comments addon though, which I suspected was going to be a pain (and I was right), I started with Generate Links for Headers, my far smaller and less complicated addon. I figured it should be a good way to get a feel for the changes that'll be required in the more complicated one. You know, a chance to get my feet wet, learn a few things and then build on that knowledge in the larger addon.

After determining that nothing in the Migrating to Manifest V3 guide applied, I changed the "manifest_version" from 2 to 3, tested it locally for 30 seconds, and uploaded it to the store. A day later, it was accepted and works as it always has. Wow. I feel like I could teach a class on this stuff now.

Taking all that I learned, it was time to tackle the larger addon. Maybe I could just bump up the version number and hope for the best? Nope.

Background pages are a no-no.

One rename in the manifest file later (so like, 3 seconds) and I was past the front gate... and greeted by a looong line of errors. But hey, it's trying to load now, so laziness ftw!

Yep, looks pretty good.

One by one, I moved down the list. Browser_action was renamed to action and browser_specific_settings is a Firefox thing which might be required in Firefox for MV3. Requesting host URLs (like I do, to periodically grab updated css selectors to block on sites) got moved into their own section called host permissions. All pretty straight-forward so far, and documented pretty well in a number of places. Here's a few I found along the way:

That last error threw me, though. What does "service work registration failed" mean? Service workers replaced background pages, which isn't cryptic, but the error itself is so vague. Why did it fail? Well, reason 15 of course! Including the error number in there required a bug fix, apparently, and oh boy what a good time that would've been to toss some more descriptive text in there. I never did find a source for what the numbers mean, but while I was flailing around for a fix, they kept switching between 3 and 15.

The problem ended up being that my background script required other scripts, which I instructed the manifest file to load in tandem. That's not allowed with service workers.

"background": {
    "scripts": [
    "persistent": false

You get to specify one file, which you can mark as a module in order to import code from other modules that export their functions. Or something. I'm sure a web developer could explain all this, but I'm not one, nor do I feel like learning about this weekend. I gave it the ol' college try, it didn't go well, and I ended up copying whatever I needed from other files into the "service worker" file itself. For the more intrepid, maybe this'll help. I decided DRY code wasn't worth my sanity.

One of the benefits of having to go through everything with a fine-tooth comb, though, was that I streamlined my background page / service worker. I realized I didn't need toastr, so I dropped that reference. jQuery is rarely a necessity, and wasn't in my service worker, so I dropped that reference too. I dropped Axios from the addon altogether, in favor of fetch. Here's a nice little comparison that I found informative: Axios vs. fetch(): Which is best for making HTTP requests?

One thing that's got me scratching my head is that this code seems to work just fine with MV3, where I inject the stylesheet into the page. I guess it's okay because it's in the content script, running within the context of the current page?

var header = document.querySelector('head');
if (header) {
} else {

The reason it had me concerned is that one of the differences between background pages and service workers is that the latter doesn't have access to the DOM. I interpreted that as not having access to the DOM at all, but it seems I was mistaken. I hope.

One of the great things about MV2 was that anyone could get out there and write an addon, and I feel like the complexities here might stymie a lot of people with neat ideas. Whether that's good or bad is a matter of opinion, like everything, but I have a tough time believing it's great.

I already linked to some of these articles throughout this post, but here's a bunch of sites I found useful while trying to migrate. Oh, and my migration is complete and uploaded, although I'm waiting for it to be accepted. And I can resolutely say I learned nothing from the hoops Google made me jump through, nor do I see how the changes I had to make led to my addon being more secure or privacy-friendly. But it's done, so whatever.

As for the Firefox store, they don't begin accepting MV3 extensions until next week, but that's a story for another time. Hopefully a really short, "I uploaded it and it worked" story.


Grant Winney

I write when I've got something to share - a personal project, a solution to a difficult problem, or just an idea. We learn by doing and sharing. We've all got something to contribute.

Comments / Reactions

One of the most enjoyable things about blogging is engaging with and learning from others. Leave a comment below with your questions, comments, or ideas. Let's start a conversation!