DEV Community

tetsu
tetsu

Posted on

Lessons learned from my Chrome extension migration to Manifest V3

This is a record of the Manifest V3 migration of Mouse Dictionary.

Background

What is Manifest V3?

Existing Chrome extensions will stop working in 2023, unless migrated to Manifest V3.

(Manifest V2 support timeline)
Manifest V2 support timeline

This is not the main topic here, so please refer to official documentation and existing articles.


Mouse Dictionary is an Manifest V2 extension released in 2018, so sooner or later it had to be migrated to V3.

Cross-browser issue

As of May 2022, Firefox does not yet support Manifest V3, so the Firefox version must remain V2. This means that cross-browser extensions need to support both V2 and V3, which is quite a hassle.

Mouse Dictionary has tried to maintain Firefox support while migrating the Chrome version to V3, so please refer to this page if you are in a similar situation.

Actual migration

There is an official migration guide available.
https://developer.chrome.com/docs/extensions/mv3/intro/mv3-migration/

The following is a record of the actual mundane migration work.

Preparation 1: Eliminate eval

Manifest V3 has more restrictions on eval() and new Function().

Mouse Dictionary was using Hogan.js as its Mustache engine, but because it was using new Function() internally, it was an obstacle in the V3 migration process.

Therefore, I eliminated new Function() by moving from Hogan.js to mustache.js.

Hogan.js, mustache.js, and Handlebars were originally considered as candidates for the Mustache engine, and Hogan.js was the fastest for the Mouse Dictionary usage.

I verified that mustache.js is compatible and fast enough so that it's capable of being the extension's new Mustache engine.

Preparation 2: Build for each browser

If you want to migrate the Chrome version to V3 and keep the Firefox version, it is not possible to prepare a single manifest.json for all browsers. package at build time.

In the case of the Mouse Dictionary, the appropriate manifest.json is included in the package at build time.

manifest

Change code and configurations

View changes on GitHub

Code

chrome.browserAction -> chrome.action

In V3, chrome.browserAction needs to be changed to chrome.action. Conversely, in V2 (Firefox), there is no chrome.action and chrome.browserAction needs to be used. In order to keep it cross-browser, some kind of device is needed.

There are many ways to realize this, but since this is the only code where cross-browser compatibility was necessary, I simply used a webpack constant.

if (BROWSER === "CHROME") {
  chrome.action.onClicked.addListener((tab) => {
    chrome.scripting.executeScript({
      target: { tabId: tab.id },
      files: ["main.js"],
    });
  });
} else {
  chrome.browserAction.onClicked.addListener(() => {
    chrome.tabs.executeScript({
      file: ". /main.js",
    });
  });
}
Enter fullscreen mode Exit fullscreen mode

By the way, the code below also works.

if (chrome.action) {
  chrome.action.onClicked.addListener((tab) => {
    chrome.scripting.executeScript({
      target: { tabId: tab.id },
      files: ["main.js"],
    });
  });
} else {
  chrome.browserAction.onClicked.addListener(() => {
    chrome.tabs.executeScript({
      file: ". /main.js",
    });
  });
}
Enter fullscreen mode Exit fullscreen mode

The former is a bit more economical because unneeded processing disappears at build time.

chrome.extension -> chrome.runtime

Since both chrome.extension and chrome.runtime work in V2 (Firefox), I simply replaced them.

- const url = chrome.extension.getURL(fname);
+ const url = chrome.runtime.getURL(fname);
Enter fullscreen mode Exit fullscreen mode

manifest.json

permissions

- "permissions": ["storage", "unlimitedStorage", "activeTab"],
+ "permissions": ["storage", "unlimitedStorage", "activeTab", "scripting"],
Enter fullscreen mode Exit fullscreen mode

background

   "background": {
- "scripts": ["background.js"],
- "persistent": false
+ "service_worker": "background.js"
   },
Enter fullscreen mode Exit fullscreen mode

commands

   "commands": {
- "_execute_browser_action": {
+ "_execute_action": {
       "description": "Activate the extension"
     },
Enter fullscreen mode Exit fullscreen mode

web_accessible_resources

- "web_accessible_resources": ["data/*.json"]
+ "web_accessible_resources": [
+ {
+ "resources": ["data/rule.json", "data/dict*.json"],
+ "matches": ["<all_urls>"]
+ }
+ ]
Enter fullscreen mode Exit fullscreen mode

Unresolved issues

Doesn't work on local files

Mouse Dictionary used to work on local HTML documents opened in Chrome, but it is no longer working after the V3 migration. I know the cause, web_accessible_resources does not work in tabs opened with file:///~, but I can't find any official information about it, so I don't know if this is an intended change in V3 or a bug in Chrome, so I am waiting and seeing.

(FYI)

Shortcut key settings behavior is strange

Mouse Dictionary can set shortcut keys, but the behavior is not quite stable after the migration to V3. It seems that shortcut keys are not reflected immediately after they are set, but are reflected after restarting Chrome. There is nothing that can be done on the extension developer side, so we are just waiting to see how it goes.

Shortcut key

Impressions

This is only a case of Mouse Dictionary, but the amount of code changed was small. However, there is still little information on the web about the experience of Manifest V3 migration, so it is difficult to research, trial and error, and verify how to change the code to make it work as well as V2.

Top comments (0)