メッセージング API
Plasmo のメッセージング API を使用すると、拡張機能の異なる部分間の通信が容易になります。messages
ディレクトリにファイルを追加するだけで、Plasmo が残りの処理をすべて行います。Plasmo メッセージングは、宣言型で、型安全、関数型、Promise ベースの API で、拡張機能コンポーネント間でメッセージの送受信、中継を行います。
インストール
1. 依存関係のインストール
@plasmohq/messaging
ライブラリは、別のリポジトリに保持されています。まず、パッケージマネージャーを使用してインストールする必要があります。
pnpm install @plasmohq/messaging
2. background フォルダとファイルの作成
@plasmohq/messaging
ライブラリでは、バックグラウンドサービスワーカーが background/index.ts
フォルダ内に存在し、すべてのメッセージハンドラーが background/*
フォルダ内に存在する必要があります。
既に background.ts
または background.js
ファイルがある場合は、background
フォルダを作成し、スクリプトを background/index.ts
または background/index.js
に移動する必要があります。
background
フォルダがまだない場合は、background
フォルダを作成し、新しい空の background/index.ts
または background/index.js
ファイルを作成します。
これで、background/
サブフォルダ内に新しいハンドラーを作成できるようになります。例えば、ping
という名前の messages
ハンドラーを作成するには、background/messages/ping.ts
を作成します。利用可能なさまざまなタイプのハンドラーとその設定方法については、ドキュメントの残りの部分を参照してください。
この時点で、フォルダ構造は次のようになる可能性があります。
.
├── background
│ ├── index.ts
│ └── messages
│ └── ping.ts
3. 静的型の生成
コンパイル時に、Plasmo はすべてのメッセージハンドラーの静的型を生成します。開発サーバーが実行されている場合は自動的に実行されます。ビルドするたびに自動的に実行されます。sendToBackground
および relayMessage
関数は、どちらもパラメーターオブジェクトの一部として name
フィールドを受け取ります。この name
フィールドは、すべてのメッセージハンドラーの名前で静的に型付けされます。
注意: 最初の型エラー
"name" is never
のような型エラーが発生する場合は、Plasmo がハンドラー型をコンパイルする必要があるためです。解決するには:
- 開発サーバーを実行する
- エディターで TypeScript サーバーを再起動する
4. 以上です
これで、Plasmo のメッセージングライブラリのインストールが完了しました。
TL;DR
メッセージング API | 送信元 | 送信先 | 一時的なもの | 永続的なもの |
---|---|---|---|---|
メッセージフロー | 拡張機能ページ/コンテンツスクリプト | バックグラウンドサービスワーカー | はい | いいえ |
リレーフロー | ウェブサイト | コンテンツスクリプト/バックグラウンドサービスワーカー | はい | いいえ |
ポート | 拡張機能ページ/コンテンツスクリプト | バックグラウンドサービスワーカー | いいえ | はい |
ポート | バックグラウンドサービスワーカー | 拡張機能ページ/コンテンツスクリプト | いいえ | はい |
ポート + リレー | バックグラウンドサービスワーカー | ウェブページ | はい | はい |
例
メッセージフロー
メッセージフローを使用して、拡張機能ページ、タブページ、またはコンテンツスクリプトとバックグラウンドサービスワーカー間で一度限りのメッセージを開始します。このフローは、重い計算をバックグラウンドサービスワーカーにオフロードしたり、CORS を回避したりする場合に役立ちます。
バックグラウンドサービスワーカーは、REST スタイルの API ハンドラーを持つメッセージハブです。メッセージハンドラーを作成するには、background/messages
ディレクトリに ts モジュールを作成します。ファイル名はメッセージ名にする必要があり、デフォルトのエクスポートはハンドラー関数にする必要があります。
import type { PlasmoMessaging } from "@plasmohq/messaging"
const handler: PlasmoMessaging.MessageHandler = async (req, res) => {
const message = await querySomeApi(req.body.id)
res.send({
message
})
}
export default handler
拡張機能ページ、コンテンツスクリプト、またはタブページは、@plasmohq/messaging
ライブラリを使用してこれらのハンドラーにメッセージを送信できます。Plasmo フレームワークが舞台裏でハンドラーをオーケストレーションするため、メッセージ名は型付けされ、エディターで IntelliSense が有効になります。
import { sendToBackground } from "@plasmohq/messaging"
...
const resp = await sendToBackground({
name: "ping",
body: {
id: 123
}
})
console.log(resp)
メインワールドにあるコンテンツスクリプトからメッセージを送信するには、リクエストに拡張機能のIDを含める必要があります。拡張機能のIDは、ビルドしてブラウザに追加した後、Chromeの拡張機能マネージャーウィンドウで見つけることができます。
import { sendToBackground } from "@plasmohq/messaging"
import type { PlasmoCSConfig } from "plasmo"
export const config: PlasmoCSConfig = {
matches: ["<all_urls>"],
world: "MAIN"
}
...
const resp = await sendToBackground({
name: "ping",
body: {
id: 123
},
extensionId: 'llljfehhnoeipgngggpomjapaakbkyyy' // find this in chrome's extension manager
})
console.log(resp)
リレーフロー
注意: リレーメッセージングAPIはパブリックアルファプレビュー版です。バグ、不完全/漏洩した抽象化、および将来のAPIの変更を予期してください。遭遇した問題については、このリンクからお知らせください。
リレーフローは、リレーと呼ばれる軽量なメッセージハンドラーを使用して、ターゲットウェブページとバックグラウンドサービスワーカー間の通信を可能にします。このリレーは、コンテンツスクリプトのrelayMessage
関数を使用して登録されます。
relayMessage
関数はwindow.postMessage
メカニズムを抽象化し、同じオリジンに一致するメッセージを検出してバックグラウンドサービスワーカーに転送するリスナーを登録します。これらのメッセージは、次にbackground/messages
の下に登録された適切なメッセージフローハンドラーによって処理されます。
sendToBackgroundViaRelay
関数は、リレーを介してメッセージを送信し、応答を待ちます。適切な処理と応答の追跡を確保するために、各メッセージに一意のインスタンスIDを生成します。
これらの関数の実装は、GitHubリポジトリ (opens in a new tab)で確認できます。
この方法は、Chrome拡張機能のドキュメントで説明されている"externally_connectable" (opens in a new tab)メソッドの代替手段を提供します。
リレーの設定
リレーを設定するには、コンテンツスクリプトでrelayMessage
関数を使用します。コンテンツスクリプトには複数のリレーを含めることができます。前の例からのping
メッセージハンドラーとウェブサイトwww.plasmo.com
を想定すると:
import type { PlasmoCSConfig } from "plasmo"
import { relayMessage } from "@plasmohq/messaging"
export const config: PlasmoCSConfig = {
matches: ["http://www.plasmo.com/*"] // Only relay messages from this domain
}
relayMessage({
name: "ping"
})
ターゲットウェブページ(例:plasmo.com
)のコードでは、次のようにsendToBackgroundViaRelay
を使用して、登録されたリレーを使用してメッセージを送信できます。
import { sendToBackgroundViaRelay } from "@plasmohq/messaging"
...
const resp = await sendToBackgroundViaRelay({
name: "ping"
})
console.log(resp)
chrome.runtime
が利用できないコンテキストからメッセージをリレーするには、relay
関数を使用できます。
import { relayMessage } from "@plasmohq/messaging"
relayMessage(
{
name: "ping"
},
async (req) => {
console.log("some message was relayed:", req)
return {
message: "Hello from sandbox"
}
}
)
ポート
ポートメッセージングAPIはパブリックアルファプレビュー版です。バグ、不完全/漏洩した抽象化、および将来のAPIの変更を予期してください。遭遇した問題については、このリンクからお知らせください。
メッセージングポートAPIは、ChromeランタイムのポートAPI (opens in a new tab)を抽象化した高レベルAPIであり、バックグラウンドサービスワーカーとの永続的な接続を確立します。
現在の実装は、バックグラウンドサービスワーカーのポートリスナーへの接続確立に重点を置いています。
BGSWポートハンドラーを作成するには、background/ports
ディレクトリにtsモジュールを作成します。ファイル名はポート名になり、デフォルトのエクスポートはハンドラー関数になります。
import type { PlasmoMessaging } from "@plasmohq/messaging"
const handler: PlasmoMessaging.PortHandler = async (req, res) => {
console.log(req)
res.send({
message: "Hello from port handler"
})
}
export default handler
拡張機能ページで、@plasmohq/messaging/port
の下にあるgetPort
ユーティリティを使用してポートを取得するか、またはusePort
フックを使用します。usePort
は現在Reactフックに依存しているため、Reactコンポーネント内で使用する必要があることに注意してください。この例は、Svelteコンポーネント内でgetPort
の使用を示しています。
<script lang="ts">
import { getPort } from "@plasmohq/messaging/port"
import { onMount, onDestroy } from "svelte"
let output = ""
const messageListener = (msg) => {
output = msg
}
const mailPort = getPort("mail")
onMount(() => {
mailPort.onMessage.addListener(messageListener)
})
onDestroy(() => {
mailPort.onMessage.removeListener(messageListener)
})
function handleSubmit() {
mailPort.postMessage({
body: {
hello: "world"
}
})
}
</script>
<div>{output}</div>
ReactでのusePort
の例を次に示します。データは常にポートハンドラーからの最新の応答を反映します。
import { usePort } from "@plasmohq/messaging/hook"
function DeltaTab() {
const mailPort = usePort("mail")
return (
<div>
{mailPort.data?.message}
<button
onClick={async () => {
mailPort.send({
hello: "world"
})
}}>
Send Data
</button>
</div>
)
}
export default DeltaTab
E2E 型安全性 (WIP)
エンドツーエンドのリクエスト/レスポンスボディの型安全性は、#334 (opens in a new tab)で進行中です。それまでは、提供されている汎用型を使用できます。
import type { PlasmoMessaging } from "@plasmohq/messaging"
export type RequestBody = {
id: number
}
export type ResponseBody = {
message: string
}
const handler: PlasmoMessaging.MessageHandler<
RequestBody,
ResponseBody
> = async (req, res) => {
console.log(req.body.id)
res.send({
message: "Hello from background"
})
}
export default handler
import { sendToBackground } from "@plasmohq/messaging"
import type { RequestBody, ResponseBody } from "~background/messages/ping"
...
const resp = await sendToBackground<RequestBody, ResponseBody>({
name: "ping",
body: {
id: 123
}
})
console.log(resp)