はじめに
ブラウザ拡張機能を作ったことがある人なら分かると思うんですが、あのmanifest.jsonの設定とか、ファイル構成とか、正直めんどくさいですよね。
個人的には「ちょっとした便利ツールを作りたいだけなのに、なんでこんなにボイラープレートが必要なの」という気持ちになることが多かった。そんな悩みを解決してくれるのが今回紹介するPlasmoというフレームワークです。
Plasmoは「ブラウザ拡張機能版のNext.js」とも言われていて、React + TypeScriptでモダンな開発体験を提供してくれます。GitHubスターは12.8kを超えていて、かなり注目されているプロジェクトですね。
特徴・メリット
Plasmoの魅力をざっくりまとめるとこんな感じです。
React + TypeScriptの第一級サポート
これ、意外と重要なんですよ。普通にChrome拡張を作ろうとすると、Webpackの設定やらTypeScriptのトランスパイル設定やら、開発環境を整えるだけで疲弊しがち。Plasmoなら最初からReact + TypeScript前提で設計されているので、その辺の面倒な設定は全部やってくれます。
manifest.jsonの自動生成
ブラウザ拡張の設定ファイルであるmanifest.jsonを手動で書く必要がない。ファイル構成から自動で生成してくれるので、開発者はロジックに集中できます。これだけでもQOL上がりますね。
ライブリロード + HMR対応
開発中にコードを変更したら、拡張機能が自動でリロードされる。React HMRも効くので、状態を保ったまま画面の変更が反映される。地味だけど開発効率がかなり違います。
複数ブラウザ対応
Chrome、Firefox、Edge向けに一つのコードベースからビルドできる。ブラウザごとにコードを書き分ける必要がないのは時短になりますね。
Storage API / Messaging API
拡張機能でよく使うストレージ管理やメッセージングの仕組みが、専用のAPIとして用意されている。車輪の再発明をしなくて済みます。
インストール方法
インストールはめちゃくちゃ簡単です。pnpmを推奨していますが、npmやyarnでも動きます。
# pnpmの場合(推奨)
pnpm create plasmo my-extension
# npmの場合
npm create plasmo my-extension
# yarnの場合
yarn create plasmo my-extension
作成されたディレクトリに移動して開発サーバーを起動するだけ。
cd my-extension
pnpm dev
これでbuild/chrome-mv3-devにビルドされたファイルが出力されます。
Chromeへの読み込み
chrome://extensionsを開く- 右上の「デベロッパーモード」をON
- 「パッケージ化されていない拡張機能を読み込む」をクリック
build/chrome-mv3-devフォルダを選択
これだけで拡張機能がインストールされます。
基本的な使い方
Plasmoのファイル構成は直感的です。Next.jsを使ったことがある人ならすぐに理解できると思います。
ポップアップの作成
拡張機能のアイコンをクリックしたときに表示されるポップアップは、popup.tsxを作るだけ。
// popup.tsx
import { useState } from "react"
function IndexPopup() {
const [count, setCount] = useState(0)
return (
<div style={{ padding: 16, minWidth: 200 }}>
<h2>カウンター拡張</h2>
<p>現在のカウント: {count}</p>
<button onClick={() => setCount(count + 1)}>
+1
</button>
</div>
)
}
export default IndexPopup
普通のReactコンポーネントですね。特別なことは何もしていない。これがそのまま拡張機能のポップアップになります。
コンテンツスクリプトの作成
Webページに対して何か処理を行いたい場合は、content.tsを作成します。
// content.ts
export {}
console.log("コンテンツスクリプトが読み込まれました")
// DOMの操作例
const heading = document.querySelector("h1")
if (heading) {
heading.style.color = "red"
}
バックグラウンドスクリプト
バックグラウンドで動作するService Workerはbackground.tsで定義。
// background.ts
export {}
chrome.runtime.onInstalled.addListener(() => {
console.log("拡張機能がインストールされました")
})
chrome.action.onClicked.addListener((tab) => {
console.log("アイコンがクリックされました", tab.url)
})
オプションページ
拡張機能の設定画面はoptions.tsxで作成。
// options.tsx
function OptionsPage() {
return (
<div style={{ padding: 20 }}>
<h1>設定</h1>
<label>
<input type="checkbox" />
機能を有効にする
</label>
</div>
)
}
export default OptionsPage
ディレクトリ構成
ファイルが増えてきたらディレクトリで整理することもできます。
my-extension/
├── popup/
│ └── index.tsx
├── options/
│ └── index.tsx
├── contents/
│ └── main.ts
├── background/
│ └── index.ts
├── assets/
│ └── icon.png
└── package.json
実践的なユースケース
Tailwind CSSとの組み合わせ
PlasmoはTailwind CSSとも相性が良いです。
pnpm create plasmo --with-tailwindcss
これでTailwind CSS込みのプロジェクトが作成されます。
環境変数の利用
.envファイルで環境変数を管理できます。
# .env
PLASMO_PUBLIC_API_KEY=your-api-key
// popup.tsx
const apiKey = process.env.PLASMO_PUBLIC_API_KEY
PLASMO_PUBLIC_というプレフィックスを付けると、クライアントサイドで参照できるようになります。
本番ビルド
ストアに公開する際は本番ビルドを行います。
pnpm build
build/chrome-mv3-prodに最適化されたファイルが出力されます。そのままChrome Web Storeにアップロードできる形式です。
GitHub Actionsでの自動公開
PlasmoはBrowser Platform Publisher(BPP)というGitHub Actionも提供しています。これを使えば、GitHubにプッシュするだけでChrome、Firefox、Edgeのストアに自動公開できます。
# .github/workflows/publish.yml
name: Publish Extension
on:
push:
tags:
- 'v*'
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
- uses: actions/setup-node@v4
- run: pnpm install
- run: pnpm build
- uses: PlasmoHQ/bpp@v3
with:
keys: ${{ secrets.SUBMIT_KEYS }}
まとめ
正直なところ、ブラウザ拡張機能の開発って敷居が高いイメージがあったんですが、Plasmoを使うとかなりハードルが下がりますね。
特に良いと思ったポイントをまとめると:
- セットアップが一瞬:
pnpm create plasmoだけで始められる - manifest.jsonを書かなくていい:ファイル構成から自動生成
- Reactの知識がそのまま活かせる:新しいことを覚える負荷が少ない
- HMRで開発体験が快適:変更が即座に反映される
- 複数ブラウザ対応:一度書けばChrome、Firefox、Edgeで動く
30代になると「新しい技術を覚える時間がない」という話をよく聞くんですが、Plasmoは既存のReact知識を活かせるので、学習コストが低いのが良いですね。
ちょっとした業務効率化ツールを作りたいとか、自分専用の便利拡張が欲しいという人には、Plasmo一択だと思います。