Lessons learned from my Chrome extension migration to Manifest V3
Tags: javascript, chrome, firefox
Published: 2022-05-14 17:18:41

---
title: Lessons learned from my Chrome extension migration to Manifest V3
published: true
description: Lessons Learned from my Migration to Manifest V3
tags: javascript,chrome,firefox
//cover_image: https://direct_url_to_image.jpg
---

This is a record of the Manifest V3 migration of [Mouse Dictionary](https://mouse-dictionary.netlify.app/en/).

## Background

### What is Manifest V3?

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

([Manifest V2 support timeline](https://developer.chrome.com/docs/extensions/mv3/mv2-sunset/))
![Manifest V2 support timeline](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cqm705raooz51ppmph7k.png)
 

This is not the main topic here, so please refer to [official documentation](https://developer.chrome.com/docs/extensions/mv3/intro/) and [existing articles](https://dev.to/search?q=manifest%20v3).

----

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()](https://developer.chrome.com/docs/extensions/mv3/mv3-migration-checklist/#:~:text=Are%20you%20executing%20remote%20code%20or%20arbitrary%20strings%3F).

Mouse Dictionary was using [Hogan.js](https://github.com/twitter/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](https://github.com/janl/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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8y33p06acp20lvrx31lf.png)
 

## Change code and configurations

[View changes on GitHub](https://github.com/wtetsu/mouse-dictionary/pull/75/files)


### 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.


```js
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",
    });
  });
}
```


By the way, the code below also works.

```js
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",
    });
  });
}
```


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.

```diff
- const url = chrome.extension.getURL(fname);
+ const url = chrome.runtime.getURL(fname);
```



### manifest.json

permissions

```diff
- "permissions": ["storage", "unlimitedStorage", "activeTab"],
+ "permissions": ["storage", "unlimitedStorage", "activeTab", "scripting"],
```

background

```diff
   "background": {
- "scripts": ["background.js"],
- "persistent": false
+ "service_worker": "background.js"
   },
```

commands

```diff
   "commands": {
- "_execute_browser_action": {
+ "_execute_action": {
       "description": "Activate the extension"
     },
```

web_accessible_resources

```diff
- "web_accessible_resources": ["data/*.json"]
+ "web_accessible_resources": [
+ {
+ "resources": ["data/rule.json", "data/dict*.json"],
+ "matches": ["<all_urls>"]
+ }
+ ]
```



## 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)

* https://stackoverflow.com/questions/69736887/web-accessible-resources-manifest-key-is-ignored-if-respective-resources-are-i
* https://bugs.chromium.org/p/chromium/issues/detail?id=1264366


### 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7ydzy62gng46qo5fafnf.png)



## 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.