Chrome Extension Manifest V3に移行して詰まったところ。

去年の暮れあたりにChrome Extension Manifest V3がリリースされました。
Welcome to Manifest V3 - Chrome Developers
ウェブストアがV3拡張を受け付けるようになって半年経つので、そろそろ対応したほうがいいだろうということで、一番パワーをつかうRight-Click-to-CalendarをV3にしました。この記事を書いている時点では審査中です。というか審査中のバージョンにめちゃくちゃでかいバグを仕込んでしまったので審査を取り下げたいのですが、取り下げできなくて困っています。

Manifest V3のここがだめ

V3でよかったと思う箇所が今の所本当に1つもないのですが、特にだめだと思った箇所を列挙します。

Message passingが完了できない

V3ではBackgroundがService Workerを使うようになりました。 Backgroundとcontent scriptとの通信にMessage passingを使用しますが、Message Passingの途中でService Workerが破棄されるという事象が発生します。 long-lived connectionでの切断については以下の記事が大変詳しくてわかりやすいです。ありがとうございます。
Chrome Extension Manifest V3 では long-lived connection が切断される

long-lived connectionに限らず、Backgroundからcontent scriptにchrome.tabs.sendMessageしても、responseを受ける前にService Workerが破棄されるため、content scriptから受け取った結果を使って何かする、という処理が難しいです。これはChromeのバグな気がするため、今後の修正に期待したいところです。(2021/07/25追記) バグのようです。詳細は後述します。
検証は以下のコードで行いました。

// background.js
/**
 * コンテキストメニュー押下時にメッセージを飛ばす
 */
const getClickHandler = (info, tab) => {
  chrome.tabs.sendMessage(tab.id, {
    message: "test",
  }, () => { // レスポンスを受け取ればタブが作成される
    // 実際はタブが作成される前にService Workerが破棄される
    chrome.tabs.create({
      "url": "options.html"
    });
  });
};
// content script
// メッセージを受け取ったら同期的にレスポンスを返す
chrome.runtime.onMessage.addListener(
  (request, sender, sendResponse) => {
    sendResponse({ message: "response" }); 
  }
);

2021/07/25追記

chrome.tabs.sendMessageでresponseを受ける前にService Workerが破棄されるのは、Chrome Apps & Extensions Developer Toolに関連するバグだそうで、無効化すると再現しなくなりました。
1214889 - chrome.tabs.sendMessage callback function does not get invoked on MV3 - chromium

Chrome Apps & Extensions Developer Toolは導入しているユーザーが相当数いるはずなので、実質このバグが修正されるまではchrome.tabs.sendMessageのresponseは使えないですね。

Storage APIがasync/awaitに対応していない

backgroundが永続化しないからStorage API使ってねと言ってるわりに使いにくいです。 Promise対応してると思ってasync/awaitで呼んでるのに、対応してなくて一切動作せず2時間溶かしました。良かったですね。(ドキュメント読んでないほうが悪い)
chrome.storage - Chrome Developers

background scriptがmanifest.jsonと同じディレクトリにない場合、動作しない

バグです。ドキュメントに書いてくれ。
1136582 - Can’t register service workers in non-root directory as the background context of extensions V3 - chromium

Service WorkerがlocalStorageに対応していない

Using Service Workers - Web APIs | MDN

Note: localStorage works in a similar way to service worker cache, but it is synchronous, so not allowed in service workers.

Chrome拡張うんぬんの問題ではなくService Workerの仕様です。BackgroundでどうしてもlocalStorageが必要な場合は、Storage APIに移行しなければなりません。V2でlocalStorageとStorage APIを同居させて裏で値をコピーしてからV3に移行するのが良さそうです。
Right-Click-to-Calendarは本来Storage APIを使う必要はなかったのですが、先述したMessage Passingのバグの影響でcontent scriptにメッセージを送り返せないため、仕方なくStorage APIを使っています。

所感

まだあった気がしますが忘れたので思い出したら追記します。
個人的な感想としては、V3移行は準備だけしておいて機能が整備されたあたりで移行するのが一番良い気がします。Meessage Passingも致命的な部分にバグがあるし急いで対応するメリットは今の所感じられませんでした。
「Manifest V3 に移行すると、審査にかかる時間を短縮し、新しい API や機能を使用できます。」とのことですが、今祝日なので審査が早くなったかは判断不能です。