Chrome拡張機能 AmazingSearcher メモ 2021/01/09 ~ 2021/03/10
このスクラップについて
Chrome拡張機能「AmazingSearcher」を作成中に得られた知見を記事にするためのまとめ
(ピン留め機能が使いたかった)
追加したいやつメモ
個人的なものも含む。順次追加
長いので折りたたむ
- 絵文字検索サイト
- 絵文字の公式のやつ(Unicode?)
- git
- CSS
- HTML
- React
- Go
- Vim
- VSCode
- AWS
- GCP
- Google Apps Script
- Notion
- Workona
- Gather
- TickTick
- Any.do
- Chrome
- Vivaldi
- webpack
- Slack
- WSL
- Windows Terminal
- Tablacus explorer
- Amzing Seacher
- Zoom
- Google Docs系など
- Figma
- Affinity
- DaVinci Resolve
- Adobe
- Office系
- Java
- PHP
- AutoHotKey
- [ ]
Chrome検索結果の右側に表示するために
idがrhs
のところ(right-hand side?)
var obj = document.getElementById('rhs');
obj.insertAdjacentHTML('beforeend', '<div>BeforeEnd Hogeeeeeeeeeeeeeeeeeeeeeeeee</div>');
obj.insertAdjacentHTML('afterbegin','<div>AfterBegin</div>')
なら上に表示できる
2021/02/09 16:29 の時点で、右側のスペースのidがrhs
である要素は補足の情報(↑の画像のChromeのロゴが載っているやつ)のみになった。
対策として、id=main
の要素に対して右側から座標を指定してあげる
Vue と Tailwind CSS で作りたい
今まで修正したらいちいちchrome://extensions/
から再読み込みしてたけど、これならホットリロードできる?
素で書くならこっち?
Figma使ってみる
ブラウザは重いのでデスクトップの方いれたら重くなかった。
プラグイン
プラグインは、この場所ではなく、"Search"か"Community"で探して入れる。
Vue x Tailwind CSS でChrome拡張機能作るフロー
devtools の導入
Vue 3 版の Vue.js devtools を入れる。
Vue プロジェクトの作成
cd ~/ghq/github.com/hoge
vue create hoge-extension
Default (Vue 3 Preview)
を選択。
Viteは追加でパッケージ入れるのが面倒だから Vue。
参考:Creating a Project | Vue CLI
Tailwind CSS を導入
前の公式ドキュメントには、
Vue 3 and Vite don't support PostCSS 8 yet so you need to install the Tailwind CSS v2.0 PostCSS 7 compatibility build for now as we've shown above.
と書かれていたので、以下のようにインストール
npm install -D tailwindcss@npm:@tailwindcss/postcss7-compat @tailwindcss/postcss7-compat postcss@\^7 autoprefixer@\^9
npx tailwindcss init -p
tailwind.config.js
のpurge: [],
をpurge: ['./src/**/*.vue'],
に書き換える。
./src/index.css
に追加
/*! @import */
@tailwind base;
@tailwind components;
@tailwind utilities;
./src/main.js
に追加
import './index.css'
manifest.json の作成
今後のために、v3のものメモ
Vue 3 の CLI
日本語のドキュメントでは、nextだけが対応しているように書いてあるが、英語のドキュメントを見ると、そんなことはない。
nextの方のCLIを使うと、TypeError: Cannot read property 'ignore' of undefined
とか 使わない変数についてのエラーが出てしまう。
Kocal/vue-web-extension はnextの方は対応していないようなので、安定版の方を使う。
Chrome Extention の Minify について
Ordinary minification, on the other hand, typically speeds up code execution as it reduces code size, and is much more straightforward to review. Thus, minification will still be allowed, including the following techniques:
* Removal of whitespace, newlines, code comments, and block delimiters
* Shortening of variable and function names
* Collapsing the number of JavaScript files
以下はOK、それ以外がだめ
- 「ホワイトスペース、改行、コメント、ブロックを区切る文字」の削除
- 変数と関数の名前を短くすること
- ファイルの数を減らすこと?
ビルドやWebpack関連のメモ
- トランスコンパイル(Babel)
- 機能ごとにjsとしてまとめる(Webpack)
ハッシュ化されたファイル名の対応をjsonで取得(shellscape/webpack-manifest-plugin)- manifest.jsonテンプレをコピー(webpack-contrib/copy-webpack-plugin)
- manifest.jsonテンプレをtransformでハッシュ化したファイル名へ変更(webpack-contrib/copy-webpack-plugin)
Build時
-
最後にzip(erikdesjardins/zip-webpack-plugin)
- ソースマップはzipに含めない
-
assets(画像等)をバンドルしたくない→publicに置く
webpack-manifest-pluginのgenerateについて
seed: 対応ファイル以外にmanifest.jsonに書き込みたいやつ
エントリーポイントのjsファイルより前に、依存をバンドルしたjsファイルを読み込む。
webpack-manifest-plugin 使用例
一部抜粋
plugins: [
new WebpackManifestPlugin({
seed: {
"manifest_version": 2,
"name": "extension name here",
"version": "0.1.0",
"description": "description here",
"icons": {},
"author": "author name here",
"content_scripts": [
{
"matches": ["https://www.google.com/search?*"],
"css": [
"main.css"
],
"js": [
"chuck-vendors.js", "main.js"
]
}
],
},
generate: (seed, _, entrypoints) => {
let newSeed = seed;
entrypoints.main.filter(fileName => {
if (fileName.match(/chunk.*js$/)) {
newSeed["content_scripts"][0]["js"][0] = fileName;
}
else if (fileName.match(/main.*js$/)) {
newSeed["content_scripts"][0]["js"][1] = fileName;
}
else if (fileName.match(/main.*css$/)) {
newSeed["content_scripts"][0]["css"][0] = fileName;
}
}
);
return newSeed;
},
})
]
参考
vue.config.jsの書き方で参考にしたコード
進捗報告 2021/02/07
大学の課題を優先していたので滞ってしまったが、以下を達成🥳
- VueのCLIではなく、直接webpackを使用してビルド
- developmentとproductionでwebpackの設定を分ける
- 共通部分は1つのファイルとして切り出し、各モードでマージする
- developmentモードでホットリロード
- productionモードでZipファイルを生成
まだ最適化されてないが 2021/02/07 19:06 の時点で、今後テンプレとして使えそうな感じである程度まとまったのが以下
minimize まとめ
minimize って何
webpackのビルド時にファイルサイズを削減したり、難読化してくれる。主にproductionモードで有効にする。
Mangling=変数を短くする
設定を変えたい
参考
terser-webpack-plugin
で terserOptions: {output: { ascii_only: false}
を指定すれば、日本語とかが変にエスケープされることはない。VueとTerserのデフォルトの設定では、ascii_only:false
になっているので特に気にかけることはない。
多分以下のような設定でできる。
\\ ...
config.optimization.minimizer('terser').tap(args => {
const { terserOptions } = args[0];
terserOptions.output.ascii_only = false;
return args
}
\\ ...
参考
Vueでcopy-webpack-plugin使うとき
vueのCLIで以下のように'copy'の名前になっている。
webpackConfig
.plugin('copy')
.use(require('copy-webpack-plugin'), [{
patterns: [{
from: publicDir,
to: outputDir,
toType: 'dir',
globOptions: {
ignore: publicCopyIgnore
}
}]
}])
なので、tapメソッドでoptionsを引き継ぐ形で書く。
config.plugin("copy").tap(([options]) => {
const manifest = {from: 'src/manifest.json'};
options = [...options, manifest];
return [options];
進捗 2021/02/10
関連情報ありなしの両方で表示可能になった。
TailwindCSS適用時にVueで差し込まれる側の要素の表示が崩れる問題
問題点
Google の検索結果ページの「すべて」のところにあるボーダーがずれている。また、検索フォーム内のマイクが超小さくなっている。
原因
TailwindCSSにより、すべての要素のCSSをいじられている(リセットのようなこと?)。↑のボーダー問題は、box-sizing
が本来の値(初期値)content-box
であったものに対してborder-box
にされていたことで生じた。
↓解決例(良くない例)
let hoge = document.querySelector("#hdtb-msb > div:nth-child(1) > div > div.hdtb-mitem.hdtb-msel");
hoge.style.boxSizing = "content-box";
ページ上のすべての要素をいじるのは、TailwindCSSのbaseの中にあるpreflightが原因(参考)。
そもそもページの中の一部の要素のみにTailwindCSSを使おうとしているのは良くない?
解決策
tailwind.config.js
でpreflight
をfalse
にする。
module.exports = {
corePlugins: {
preflight: false,
}
}
参考
box-sizingとは?
prefix付けてくれるやつあった
解決策2
tailwind.config.js
でpreflight
をfalse
にするのではなく、postcss-prefix-selector
でTailwindCSSのすべてのセレクタにprefixをつける。
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
'postcss-prefix-selector': {prefix: '#amzSchRoot'}
},
}
#amzSchRoot
はVueで差し込む要素のルートのid
TailwindCSSで訪問済みリンクの色を変える
visitedがTailwindCSSにもあるけど、デフォルトではオフになっているため設定が必要。
module.exports = {
variants: {
extend: {
textColor: ['visited'],
}
},
}
設定すれば、以下のように使える。
<a class="text-xl text-blue-600 visited:text-purple-600">hoge</a>
Vue で作る Chrome拡張機能 で画像を読み込む方法
画像をVueで作ったChrome拡張機能のスクリプト内でエンコードせずに読み込みたい場合、少し工夫がいる。
画像の配置は以下。
extension
├── public
│ └── imgs
│ └── hoge.svg
├──...
パスをメソッドに渡す
パスを指定するときは、"imgs/hoge.svg"
ではなく、chrome.extension.getURL("imgs/hoge.svg")
のように指定すること。
これを指定しないと、Chrome拡張機能のスクリプトが差し込まれる側のURLからリソースを探そうとしてしまう。
manigest.jsonに追記
manigest.json
に、 "web_accessible_resources": ["imgs/*"]
を追記する。ただし、これはpublic/imgs
を指すのではなく、ビルド後の dist/imgs
を指す。
これを指定しないと、Chrome拡張機能のフォルダ(ここではビルド後の dist/imgs
)からリソースを探せなくなってしまう。
eslintの設定を追加
先程のchrome.extension.getURL
のchrome
なんて知らない!って言われてしまうので、env
のwebextensions
をtrueに設定する。
参考
以下のリンクはmanifestのVersionが2だけど、3も同様っぽい。
進捗報告 2021/02/13
HeroiconsのSVGを表示できるようにした。
ボーダー、フォントサイズ、パディングやマージンは、ページの他の部分に近いような色やサイズにした。
訪問済みリンクの色はこのままで良いのか微妙。
「Search By Google」の下にAPIとか使った検索結果を表示しようと思ったけど、無料でも有料でも制限があるので表示しないことにした。
設定ファイルについて
jsonだと、見やすくしようとすると{
だけの行とか出るのが個人的にちょっとアレなのでyaml。
yamlはloaderで読み取ってほしい(=webpackを通す)ので、public
ではなくsrc/assets
下に配置。
と思ったけど、fetch使って設定を追加させるのなら、jsonのほうが良さそう。
進捗報告 2021/02/17
loaderと正規表現を使ってyamlファイルを処理したものを表示できた。
いよいよ次は「設定ファイルで指定された単語で検索された場合のみ表示」する。
URLからqパラメータを取得する
↓正規表現とか使わず、location.search
とURLSearchParams
でできる。
json-loader でエラー
Module parse failed: Unexpected token m in JSON at position 0 while parsing near 'module.exports = {"i...'
jsonのローダーを変えるときは、webpackの設定の時のtype
にjavascript/auto
を指定する。
例えば、vue.config.jsなら以下のように指定する。
module.exports = {
chainWebpack: config => {
config.module
.rule('json')
.test(/\.json$/)
.type('javascript/auto')
.use('json-loader')
.loader('json-loader')
.end()
},
}
参考
進捗報告 2021/02/23
- ホームページが英語と日本語など両方あっても良いようにした
- 検索結果とデータのマッチングが複数あったら1つだけではなく全部表示できるようにした
- 検索結果とマッチングした名前("Python"や"Numpy")を表示するようにした
オプションページの作成
↓ドキュメント
ついでにmanifestをv3にした。チェックリストは以下↓
Vue3 x Chrome Extension manifest v3?
modeがdevelopmentだと、Vueはeval
を使うので、下記のようなエラーが出る。
今までのmanifest v2 であれば、CSPのscript-srcに'unsafe-eval'を指定できたが、v3では指定できなくなった。
Vue CLIじゃなくwebpackなら平気
Webpackのビルドの表示を抑えたいとき
stats: 'minimal'
を指定すると、バンドルしたときのモジュール数のみになる。
2021/03/06 23:35現在は以下
// ...
module.exports = merge(common, {
stats: {
colors: true,
hash: false,
version: false,
timings: false,
assets: false,
chunks: false,
modules: false,
reasons: false,
children: false,
source: false,
publicPath: false
},
// ...
}
こうすると、以下のような出力になる。
> amazing-searcher@0.1.0 serve /home/eetann/ghq/github.com/eetann/amazing-searcher
> NODE_ENV=development webpack --config=webpack.dev.js --mode=development
Built at: 03/06/2021 11:34:58 PM
Entrypoint content = chunk.js content.css content.js
Entrypoint reload = reload.js
もっとはやくに知りたかったなぁ
参考
ターミナルでのconsole.log()
で色を付けたいとき
const reset = '\u001b[0m';
const green = '\u001b[32m';
これらを文字列に結合する。
WebSocket 参考
進捗報告 2021/03/10
developementモードでManifest v3に対応する拡張機能自動リロードを実装。具体的な機能は以下。
- 拡張機能の
content_scripts
かoptions_page
が開かれていれば、拡張機能のスクリプト変更時に拡張機能を再読み込みする -
content_scripts
が開かれていれば、拡張機能再読み込み時に関連タブを自動リロード -
options_page
が開かれていれば、拡張機能再読み込み時にオプションページを自動で開く
options_page
は拡張機能再読み込み時に自動で閉じてしまうため、リロードではなく再び「開く」ことにした。
Service Worker
は、必要に応じて終了してしまう
-
WebSocket
を使うことで、ファイル変更時にサーバーから各ページにリロードせよと伝えることができた - この仕様が原因で、スクリプト変更時に「
WebSocket
を使ってサーバーから直接Service Worker
へメッセージを送る」ことができない。そのため、「WebSocket
を使ってサーバーからcontent_scripts
かoptions_page
を経由し、chrome.runtime
を使って前者からService Worker
へメッセージを送る」ことになった
今までの拡張機能の中で一番詰まったけど、WebSocketの勉強になった。
この拡張機能自動リロードはwebpackのローカルのプラグインとして書いたので、AmazingSeacherが形になったらちゃんとしたプラグインにして、記事にしたい。
Close
長すぎてあとから探しづらくなるので、このスクラップはここで一旦閉じる。
続きは以下。