Open7

VueでChrome extensionを開発する

totatota

CRXJSを使うと開発中のホットリロードが使えて良さそう

totatota

Chrome拡張の機能

公式ドキュメント: Extensions - Chrome Developers
サンプル集: GitHub - GoogleChrome/chrome-extensions-samples: Chrome Extensions Samples

Manifest V2 と V3について

Chrome extensionで現在利用できる仕様はManifest V2Manifest V3がある
Manifest V2は近々廃止される予定なので新規でextensionを作る場合はManifest V3
を利用する
chrome extensionについて調べるとmanifestv2の情報が混在してるので注意

機能

  • ポップアップ
  • 設定
  • バックグラウンド処理
    がある

CRX JSを利用してプロジェクトを作成する

Create a project | CRXJS Vite Plugin

npm init vite@latest
Need to install the following packages:
  create-vite@4.2.0
Ok to proceed? (y) y
✔ Project name: … vite-project
✔ Select a framework: › Vue
✔ Select a variant: › TypeScriptcd
cd vite-project
npm i @crxjs/vite-plugin@beta -D

vite.configをの内容を以下に変更
Cannot find module './manifest.json'. Consider using '--resolveJsonModule' to import module with '.json' extension.ts(2732)
のエラーが出るが解決法がわからない。一旦無視でも動く

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { crx } from '@crxjs/vite-plugin'
import manifest from './manifest.json' assert { type: 'json' }

export default defineConfig({
  plugins: [
    vue(),
    crx({ manifest }),
  ],
})

manifest.jsonを作成する

{
    "manifest_version": 3,
    "name": "CRXJS Vue Vite Example",
    "version": "1.0.0",
    "action": { "default_popup": "index.html" }
}

npm run devを実行してローカルで画面ひらけばOK

chromeでchrome://extensions/を開く
Finderから vite-project/distフォルダを画面にドラッグドロップするとchrome拡張が追加される

追加した拡張機能をクリックすると、ポップアップで先ほどのローカルと同じ画面が開く

totatota

ポップアップ
manifest.jsonの action で内容を設定する
default_popupに利用するhtmlを指定する

{
    "action": { 
        "default_title": "Chrome Extension",
        "default_popup": "src/pages/popup/index.html",
        "default_icon": {
            "16": "public/icon_16.png",
            "48": "public/icon_48.png",
            "128": "public/icon_128.png"
        }
    }
}

Vueファイルをhtmlに変換したものをpopupに利用するため、以下の設定をする

src/pages/popupフォルダを作り以下を追加する。

App.vue
<script setup lang="ts">
import OptionPage from '../../components/OptionPage.vue';

</script>

<template>
  <OptionPage/>
</template>
index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Regex Url Blocker</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="./main.ts"></script>
  </body>
</html>
main.ts
import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')

vite.configに以下の設定を追加

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { crx } from '@crxjs/vite-plugin'
import { resolve } from 'path'
import manifest from './manifest.json' assert { type: 'json' } // Node >=17


export default defineConfig({
  plugins: [
    vue(),
    crx({ manifest }),
  ],
  build: {
    rollupOptions: {
      input: {
        popup: resolve(__dirname, 'src/pages/popup/index.html'),
      },
    },
  }
})

これでビルド時にdist/src/pages/popup/index.htmlが作成される

オプションページ

ポップアップと同様の手順でsrc/pages/popupを追加

totatota

ポップアップ

distフォルダ内にポップアップ用のhtmlsrc/pages/popup/index.htmlを作成するため以下の設定をする

manifest.jsonの action でポップアップページで参照するhtmlを指定

{
    "action": { 
        "default_popup": "src/pages/popup/index.html"
    }
}

npm install @types/node -Dを実行後
vite.configの内容を以下に変更

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { crx } from '@crxjs/vite-plugin'
import { resolve } from 'path'
import manifest from './manifest.json' assert { type: 'json' } // Node >=17


export default defineConfig({
  plugins: [
    vue(),
    crx({ manifest }),
  ],
  build: {
    rollupOptions: {
      input: {
        popup: resolve(__dirname, 'src/pages/popup/index.html'),
      },
    },
  }
})

src/pages/popupフォルダを作り以下を追加する。
App.vue

App.vue
<script setup lang="ts">
import HelloWorld from '../../components/HelloWorld.vue';
</script>

<template>
    <HelloWorld msg="popup page" />
</template>

index.html

index.html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>chrome extension template</title>
</head>

<body>
    <div id="app"></div>
    <script type="module" src="./main.ts"></script>
</body>

</html>

main.ts

main.ts
import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')

npm run dev でポップアップ内に以下の画面が出ればOK


→ポップアップがうまく出ないので原因調査

totatota

ポップアップがうまく出ないので原因調査
→ファイル名をtypoしていた

オプションページ

ポップアップと同様の手順で作成する

vite.configに静的html作成の設定を追加

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { crx } from '@crxjs/vite-plugin'
import { resolve } from 'path'
import manifest from './manifest.json' assert { type: 'json' }

export default defineConfig({
  plugins: [
    vue(),
    crx({ manifest }),
  ],
  build: {
    rollupOptions: {
      input: {
        popup: resolve(__dirname, 'src/pages/popup/index.html'),
        option: resolve(__dirname, 'src/pages/option/index.html'),
      },
    },
  }
})

src/pages/option配下にApp.vue,index.html,main.tsを作成する。

manifest.jsonにoptions_page項目を追加

{
    "manifest_version": 3,
    "name": "Chrome-extension-template",
    "version": "1.0.0",
    "action": { 
        "default_popup": "src/pages/popup/index.html"
    },
    "options_page": "src/pages/option/index.html"
}

npm run devを再実行し、右クリックからオプションを選択して画面が開けばOK

→今度は404になる

totatota

オプションページ

ポップアップと同様の手順で作成する

vite.configに静的html作成の設定を追加

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { crx } from '@crxjs/vite-plugin'
import { resolve } from 'path'
import manifest from './manifest.json' assert { type: 'json' }

export default defineConfig({
  plugins: [
    vue(),
    crx({ manifest }),
  ],
  build: {
    rollupOptions: {
      input: {
        popup: resolve(__dirname, 'src/pages/popup/index.html'),
        option: resolve(__dirname, 'src/pages/option/index.html'),
      },
    },
  }
})

src/pages/option配下にApp.vue,index.html,main.tsを作成する。
App.vue

App.vue
<script setup lang="ts">
import HelloWorld from '../../components/HelloWorld.vue';
</script>

<template>
    <HelloWorld msg="option page" />
</template>

index.html

index.html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>chrome extension template</title>
</head>

<body>
    <div id="app"></div>
    <script type="module" src="./main.ts"></script>
</body>

</html>

main.ts

main.ts
import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')

manifest.jsonにoptions_page項目を追加

{
    "manifest_version": 3,
    "name": "CRXJS Vue Vite Example",
    "version": "1.0.0",
    "action": { "default_popup": "src/pages/popup/index.html" },
    "options_page": "src/pages/option/index.html"
}

npm run devを再実行し、リロード後右クリックからオプションを選択して画面が開けばOK