背景とか AI とか
たまに Chrome 拡張開発をするのだが、その度に混乱することがある。 それが ESModule を使うのか CommonJS を使うのか、ということだ。
昨今は仕事でもプライベートは基本的に ESM を使っていて、 require なんて全く見なくなった。
だから油断すると import 文を書いてしまうわけだが、 Chrome 拡張機能においては Cannot use import statement outside a module というエラーに見舞われる。もはやトラウマものである。

この件を AI や AI Editor に聞いてみると、やれ ESModule は使える、指定するファイルが悪いので直しましょうか、など言われるが、どれも検討違い。 AI に任せても今は解決するフェーズにないらしい。
おそらくだが Chrome 拡張機能に関しては "実装→結果を確認→実装を修正" というフィードバックループを回すことができず、インターネットの断片的情報だけしか学習データを持っておらず、 AI の苦手分野なのだと思う。
Gemini Pro 3 がマルチモーダルへの対応性能を見せ、 Antigravity が画面の操作を AI Feedback loop の中に持ち込めるようになったのが先月で、AI 性能はまだブラウザそのものを AI で操作する範囲に収まっており、Chrome 拡張を load して自動で開発を行うフェーズには至っていない(あるいは興味を向けられていない)
本題
AI への脱線はこれくらいにして、本題というか知識。
Chrome 拡張機能で使われる主なファイルそれぞれについて、対応しているモジュールシステムが違う
content scripts : manifest の content_scripts で静的に登録される「普通のスクリプト」であり、ページに埋め込まれるスクリプトと同様に扱われるため、 import を直接書いてもモジュールとして扱われない。
background : ESModule は利用可能。Manifest V3 から background は service worker になり、type: "module" を指定すると import/export が使えます。
popup / options の HTML : popup.html に <script type="module"> を置けば ESModule が使える。
ということで、冒頭の Cannot use import statement outside a module は content_scripts にて import 文があると発生するエラー。
さて、content scripts についても ESModule で実装した上で import 文が出ない様に webpack でバンドルすればいいじゃんという話はあるが、それは AI が答えてくれるので筆を譲ることにする。