Web Extension
Web Extensions は、多くのブラウザで動作するブラウザ拡張機能を構築するためのAPIセットです。Parcelは、@parcel/config-webextension
を使用してWeb Extensionsの構築をサポートしています。
はじめに
#最初に、プロジェクトに@parcel/config-webextension
をインストールします。
yarn add @parcel/config-webextension --dev
次に、拡張機能のエントリポイントとなるmanifest.jsonファイルが必要です。このガイドで設定方法の詳細を確認してください。Manifest V2とV3の両方がサポートされています。Web Extensionコード内では、TypeScript、Vue、およびParcelでサポートされているその他の言語を使用できます。
{
"manifest_version": 3,
"name": "Sample Web Extension",
"version": "0.0.1",
"background": {
"service_worker": "background.ts",
"type": "module"
},
"content_scripts": [{
"matches": ["*://github.com/parcel-bundler/*"],
"js": ["parcel-content-script.ts"]
}]
}
拡張機能をビルドするには、manifest.json
をエントリとして、@parcel/config-webextension
をconfigとして使用してParcelを実行します。
parcel build manifest.json --config @parcel/config-webextension
プロジェクトに.parcelrc
ファイルを作成して@parcel/config-webextension
を拡張することもできます。これにより、毎回Parcel CLIに--config
オプションを渡す必要がなくなります。
{
"extends": "@parcel/config-webextension"
}
HMR
#MV3のコンテンツセキュリティポリシーの制限により、HMRはサポートされていませんが、コードを更新すると拡張機能が再読み込みされます。MV2では、HMRはデフォルトで完全にサポートされています。コンテンツスクリプトを含むページを再読み込みすると、両方のバージョンで拡張機能が再読み込みされます。
最適な開発エクスペリエンスを得るには、開発ビルドに--host localhost
を使用してください(コンテンツスクリプトの再読み込みに必要な場合があります)。次の設定をコピーできます。
{
"scripts": {
"start": "parcel watch src/manifest.json --host localhost --config @parcel/config-webextension",
"build": "parcel build src/manifest.json --config @parcel/config-webextension"
}
}
yarn start
またはnpm start
を実行すると、開発サーバーが開始されます。ソースマップとHMRは、バックグラウンドスクリプト、ポップアップページ、オプションページで機能します。MV2では、HMRは通常、コンテンツスクリプトでも機能します。
ブラウザに拡張機能を追加するには、Parcelの出力フォルダを展開して読み込みます。たとえば、Chromeでは、chrome://extensions
ページで「展開して読み込む」をクリックし、path/to/project/dist
を選択します。
yarn build
またはnpm run build
を実行すると、公開準備が整った最終的なWeb Extensionパッケージが生成されます。出力ディレクトリをzip圧縮した後、Chrome Webストアなどの選択したプラットフォームにファイルをアップロードできます。
特別な考慮事項
#予期しないメッセージ
#開発モードでは、コンテンツスクリプトページが再読み込みされるたびに、バックグラウンドスクリプトはコンテンツ{ __parcel_hmr_reload__: true }
を含むメッセージイベントを受信します。Parcelはこれを自動的に使用して、必要に応じて拡張機能を更新します。したがって、バックグラウンドスクリプトが受信するメッセージに__parcel_hmr_reload__
プロパティがないことを確認してから処理する必要があります。
スタイル
#コンテンツスクリプトでインポートされたスタイルは、そのコンテンツスクリプトのcss
プロパティに挿入され、ページ全体に適用されます。通常はこれが望ましいですが、そうでない場合は、CSSモジュールを使用して、スタイルが元のサイトに適用されないようにすることができます。
さらに、コンテンツスクリプトのCSSは、挿入されたサイトへのリンクを解決するため、ローカルアセットを参照することはできません。この問題を解決するには、バンドルをインライン化する必要があります。
.my-class {
/* Equivalent to: https://injected-site.com/custom-bg.png */
/* This is probably not what you want! */
background-image: url(./custom-bg.png);
}
.my-other-class {
/* This will use the local file custom-bg.png */
background-image: url(data-url:./custom-bg.png);
}
最後に、コンテンツスクリプトのimport()
内からリンクされたCSSを追加または削除すると、ホットリロードが機能しない場合があります。一方、同期import
にはそのような問題はありません。これは既知の制限であり、今後のバージョンで修正される予定です。
web_accessible_resources
#コンテンツスクリプトで使用されるリソースは、自動的にweb_accessible_resources
に追加されるため、通常はweb_accessible_resources
に何も指定する必要はありません。たとえば、次のコンテンツスクリプトは問題なく動作します。
import myImage from 'url:./image.png';
const injectedImage = document.createElement('img');
injectedImage.src = myImage;
document.body.appendChild(injectedImage);
ただし、拡張機能のリソースを他の拡張機能またはWebサイトからアクセスできるようにする必要がある場合は、web_accessible_resources
内にファイルパスまたはglobを指定できます。Parcelはweb_accessible_resources
のエントリをUnix globとして扱います(つまり、examples/*.png
はexamplesフォルダ内のすべてのPNGを取得し、examples/**.png
は再帰的に行います)。これは、常に再帰的なChromeのグロビングとは異なります。