はじめに
chrome拡張機能を作ろうと思ったんだけど、手動でやるといろいろ面倒だったので、こないだリリースしたらしいフレームワーク Plasmo を使ってみた。それをまとめる。
やってみる
もうさっそくやっちゃうよ。
Plasmoをinit
# フレームワークの作成 $ pnpm create plasmo .../Library/pnpm/store/v3/tmp/dlx-88105 | +2 + Packages are hard linked from the content-addressable store to the virtual store. Content-addressable store is at: /Users/ayumu-1212/Library/pnpm/store/v3 Virtual store is at: ../../Library/pnpm/store/v3/tmp/dlx-88105/node_modules/.pnpm .../Library/pnpm/store/v3/tmp/dlx-88105 | Progress: resolved 2, reused 0, downloaded 2, added 2, done 🟣 Plasmo v0.80.0 🔴 The Browser Extension Framework 🟡 Extension name: auto-diary 🟡 Extension description: An extension that automatically measures the engineer's daily progress. 🟡 Author name: ayumuabe1434@gmail.com 🔵 INFO | Creating new project with popup 🔵 INFO | Installing dependencies... Downloading registry.npmjs.org/typescript/5.1.6: 7.15 MB/7.15 MB, done Downloading registry.npmjs.org/@parcel/transformer-js/2.9.3: 45.7 MB/45.7 MB, done WARN deprecated stable@0.1.8: Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility Downloading registry.npmjs.org/@swc/core-darwin-arm64/1.3.69: 12.8 MB/12.8 MB, done Downloading registry.npmjs.org/@swc/core-darwin-arm64/1.3.66: 12.1 MB/12.1 MB, done Packages: +544 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Packages are hard linked from the content-addressable store to the virtual store. Content-addressable store is at: /Users/ayumu-1212/Library/pnpm/store/v3 Virtual store is at: node_modules/.pnpm node_modules/.pnpm/@parcel+watcher@2.1.0/node_modules/@parcel/watcher: Running install script, done in 785ms node_modules/.pnpm/sharp@0.32.1/node_modules/sharp: Running install script, done in 4.6s Progress: resolved 607, reused 1, downloaded 543, added 544, done node_modules/.pnpm/@swc+core@1.3.66/node_modules/@swc/core: Running postinstall script, done in 345ms node_modules/.pnpm/@swc+core@1.3.69/node_modules/@swc/core: Running postinstall script, done in 816ms node_modules/.pnpm/esbuild@0.18.13/node_modules/esbuild: Running postinstall script, done in 1s node_modules/.pnpm/msgpackr-extract@3.0.2/node_modules/msgpackr-extract: Running install script, done in 1.2s node_modules/.pnpm/lmdb@2.7.11/node_modules/lmdb: Running install script, done in 1s dependencies: + plasmo 0.80.0 + react 18.2.0 + react-dom 18.2.0 devDependencies: + @plasmohq/prettier-plugin-sort-imports 4.0.1 + @types/chrome 0.0.241 + @types/node 20.4.2 + @types/react 18.2.15 + @types/react-dom 18.2.7 + prettier 3.0.0 + typescript 5.1.6 WARN Issues with peer dependencies found . └─┬ plasmo 0.80.0 └─┬ @plasmohq/parcel-config 0.38.4 └─┬ @parcel/config-default 2.9.3 └─┬ @parcel/optimizer-htmlnano 2.9.3 └─┬ htmlnano 2.0.4 └── ✕ unmet peer svgo@^3.0.2: found 2.8.0 in @parcel/optimizer-htmlnano Done in 34.2s 🔵 INFO | Initializing git project... 🟢 DONE | Your extension is ready in: /Users/ayumu-1212/Documents/develop/auto-diary To start hacking, run: cd auto-diary pnpm dev Visit https://docs.plasmo.com for documentation and more examples.
おーーできた。階層構造は以下。
. ├── README.md ├── assets │ └── icon.png ├── node_modules/ ├── package.json ├── pnpm-lock.yaml ├── popup.tsx └── tsconfig.json
buildして、公開するbuildファイルを作ってみる。
$ pnpm build > auto-diary@0.0.1 build /Users/ayumu-1212/Documents/develop/auto-diary > plasmo build 🟣 Plasmo v0.80.0 🔴 The Browser Extension Framework 🔵 INFO | Prepare to bundle the extension... 🔵 INFO | Loaded environment variables from: [] 🟢 DONE | Finished in 849ms! $ tree . ├── README.md ├── assets │ └── icon.png ├── build │ ├── chrome-mv3-dev │ │ ├── icon128.plasmo.c11f39af.png │ │ ├── icon16.plasmo.9f44d99c.png │ │ ├── icon32.plasmo.83dbbbab.png │ │ ├── icon48.plasmo.a78c509e.png │ │ ├── icon64.plasmo.15206795.png │ │ ├── manifest.json │ │ ├── plasmo-default-background.e198ef58.js │ │ ├── popup.7d3dc21e.js │ │ └── popup.html │ └── chrome-mv3-prod │ ├── icon128.plasmo.3c1ed2d2.png │ ├── icon16.plasmo.6c567d50.png │ ├── icon32.plasmo.76b92899.png │ ├── icon48.plasmo.aced7582.png │ ├── icon64.plasmo.8bb5e6e0.png │ ├── manifest.json │ ├── popup.100f6462.js │ └── popup.html ├── node_modules/ ├── package.json ├── pnpm-lock.yaml ├── popup.tsx └── tsconfig.json
これでbuildができたね。公開してみよう。
拡張機能を早速表示
いったん表示までしてみよう。ぼくはbraveを使っているのでここをブラウザで開く。
そして右上の デベロッパーモード をオンにする。
そして、[パッケージ化されていない拡張機能を読み込む] を押し、 build/chrome-mv3-dev
を選択する。
すると、さっそく読み込まれて表示されている!!
chromeの履歴を取得できるようにしてみる。
最初の立ち上げ時はコードはこのようになっている。
import { useState } from "react" function IndexPopup() { const [data, setData] = useState("") return ( <div style={{ display: "flex", flexDirection: "column", padding: 16 }}> <h2> Welcome to your <a href="https://www.plasmo.com" target="_blank"> {" "} Plasmo </a>{" "} Extension! </h2> <input onChange={(e) => setData(e.target.value)} value={data} /> <a href="https://docs.plasmo.com" target="_blank"> View Docs </a> </div> ) } export default IndexPopup
まずは、history
パーミッションをmanifest.json
に設定しないといけない。
直接書き込むのではなく、package.jsonに以下を追記する。
"manifest": { "host_permissions": [ "https://*/*" ], + "permissions": [ + "history" + ] }
こうすることで、manifest.json
に自動的に反映された。
popup.tsx
を編集する。
import { useState } from "react" function IndexPopup() { + const [historyItems, setHistoryItems] = useState<chrome.history.HistoryItem[]>([]) + + const getHistory = async() => { + const now = new Date() + + const text = "" + const startTime = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1, 0, 0, 0).getTime() + const endTime = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0).getTime() + const maxResults = 10 + const items = await chrome.history.search({ + text, + startTime, + endTime, + maxResults, + }) + setHistoryItems(items) + } return ( <div style={{ display: "flex", flexDirection: "column", padding: 16 }}> <h2> Welcome to your <a href="https://www.plasmo.com" target="_blank"> {" "} Plasmo </a>{" "} Extension! </h2> + <button id="getHistory" onClick={getHistory}>getHistory</button> + <div> + <ul> + {historyItems.map((item) => (<li id={item.id} key={item.id}>{item.title}</li>))} + </ul> + </div> </div> ) } export default IndexPopup
いいねぇ、ボタンを押したら検索履歴が表示できるようになった。
とりあえずここまで!