🌅

ブラウザ拡張のためのフレームワークplasmoをVueで使う

2023/06/18に公開

plasmoとは?

ブラウザ拡張開発のためのフレームワークです。

https://www.plasmo.com

plasmoでできることに関してはこの記事に詳しいです。私もこの記事でplasmoを知りました。

https://zenn.dev/nado1001/articles/plasmo-browser-extension

React, Vue, Svelteをサポートしていると書いてありますが、Reactがデフォルトで、Vueはオプションという位置づけのようです。Vueを使うための日本語の情報があまり見当たらなかったので、ここに書き残しておきます。

plasmoの推奨はpnpmのようですが、筆者がnpmを使用しているためnpmで記述します。適宜読み替えてください。

導入手順

Getting Startedを見ると、npm create plasmoで空のプロジェクトを作成する、とありますが、これで作成されるテンプレートはReact向けのプロジェクトです。

https://github.com/PlasmoHQ/plasmo/issues/294
ここに npm create plasmo <name> -- with-vue でVue向けのテンプレートがセットアップできると書いてありますが筆者は未確認です。

ReactのテンプレートをVue向けに変更するには

React関連のPackageを削除してから、Vueを追加します。

npm rm react react-dom
npm rm -D @types/react @types/react-dom
npm i vue

つぎに、.tsxファイルを.vueに置き換えます。

popup.vue
<script lang="ts" setup>
import { ref } from "vue"
const name = ref("plasmo")
</script>

<template>
  <div>Hello, {{ name }}!</div>
</template>

これで.vueファイルを読んでくれるようになるはずです。あとは、公式のドキュメントの.tsxを.vueに読み替えつつなんとかします。

トラブルシューティング

Content Scripts UIが動かない!

Content Scripts UIを使う際は、適宜必要なメソッドなどをexportすると公式ドキュメントに書いてありますが、これはReactの場合で、Vueの場合はそれでは動きません。export defaultの中にplasmoを定義し、そこに含めてあげる必要があります。

content.vue
export default {
	plasmo: {}, // exportしたいメソッドやオプションを記述する	
}

<script setup>と併用できます。

content.vue
<script setup lang="ts">
const hoge = ref(123)
// ...
</script>

<script lang="ts">
export default {
	plasmo: {}, // exportしたいメソッドやオプションを記述する	
}
</script>

CSUIのスタイルが当たらない

vueファイルに記述したスタイルは、まとめてcontent.cssとして吐き出され、content scriptsによってページ本体に追加されます。一方で、CSUIの要素は<plasmo-csui>というCustom ElementsのShadow DOM内に生成されるため、本体のCSSが効きません。拡張によって追加した要素が元のHTMLを汚染しないという点ではよいのですが、スタイルも効かないのでは本末転倒です。

Plasmo公式のチュートリアルを見ると、getStyleメソッドをexportする手段が紹介されていますが、テンプレートやスクリプトと同じファイルにスタイルを記述できる、scopedによって命名の手間が減り管理が楽になる、などのVueの強みが生かされない方法だと個人的には感じます。これではVueを使う意味は半減と言ってよいでしょう。

実はカスタム要素を生成させず、元のページと同じ階層にdomをレンダリングする方法もあるにはあります。こちら によれば、getRootContainer 関数をエクスポートすればよいようです。ユースケースには次のような例が上がっています。

・挿入先のページのスタイルを吸収する必要がある場合。
・Shadow DOMではなく、ページと同じ階層に直接DOMを描画する必要がある場合。
・iframeを使う場合。

ただ、vueのスタイルを当てるという目的だけのためにこれを使うのは、やはり疑問符が立ちます。上にもありますが、元のページのスタイルの影響をモロに受けるためです。vueファイルから生成したCSSを、自動でshadow dom内に挿入できるのが一番スマートに解決するのですが・・・。

拡張機能のエラーが出る

__VUE_OPTIONS_API____VUE_PROD_DEVTOOLS__ を定義しなさいよというエラーが出ます。tree shakingに悪影響ですよという内容なのですが、無視して構いません。グローバルにこれらの変数を定義してあげれば消えるのですが、どうもそのような方法が見つけられていません。

おわりに

このような状況を見るに、まだvueのサポートは完全とは行かないようです。まだバージョンは0.xのプロジェクトですから、やる気のある方はissueを立ててみたり、プルリクを投げてみるのもいいのかもしれませんね。

内容に間違いがあればコメント等でお知らせください。

Discussion