TypeScriptでChrome拡張機能を作る

qlog公式からのメッセージ:ログインをしていなくてもいいねを押すことができます!

やりたいこと
・特定のウェブサイトにアクセスした時に自作のJavaScriptを動かしたい
・TypeScriptで記述したい (トランスパイルが必要)
・クラスや機能ごとにファイルを分割したい (モジュールバンドラ(Webpack)が必要)
・Windows

package.jsonの配置

npm init

TypeScriptとWebpackのインストール

npm install  typescript @types/chrome ts-loader webpack-cli --save-dev

TypeScriptの設定

package.jsonと同じフォルダにtsconfig.jsonを作成

tsconfig.json

{
    "compilerOptions": {
      "rootDir": "src", //コードファイルの配置場所
      "outDir": "dist", //変換後の出力先フォルダ
    },
    "exclude": [
      "node_modules"
    ]
}

Webpackの設定

package.jsonと同じフォルダにwebpack.config.jsを作成

webpack.config.js

const path = require("path");
module.exports = {

  // 変換するファイルを指定
  entry: {
    index: './src/index.ts',
    second: './src/second.ts'
  },

  // 出力先を指定
  output: {
    path: path.join(__dirname, "dist"),
    filename: "[name].js",
  },

  // TypeScriptを変換することを指示
  module: {
    rules: [
      {
        use: "ts-loader",
        exclude: /node_modules/,
      },
    ],
  },

  // コードでimportを書いた時の拡張子を指定
  resolve: {
    extensions: [".ts", ".js"],
  },

  // バンドル後のevalがcspに引っかかるのを回避
  devtool: 'cheap-module-source-map',
};

コードを作成

src/index.tsを次の様に書く

src/index.ts

import { Clazz } from "./classes/clazz";

window.addEventListener( 'load', () =>{
  let clazz = new Clazz();
  clazz.hello();
})

src/classes/clazz.tsを次の様に書く

src/classes/clazz.ts

export class Clazz {
  hello(){
    alert('hello');
  }
}

src/second.tsを次の様に書く

src/second.ts

window.addEventListener( 'load', () =>{
  const button = document.createElement('button');
  button.innerHTML= 'テスト';
  button.className = 'test-button';

  const body = document.getElementsByTagName('body')[0];
  body.appendChild(button);
});

トランスパイル

package.jsonにbuildコマンドを追加

package.json

{
    ...

    "scripts": {
      "test": "echo \"Error: no test specified\" && exit 1",
      "build": "webpack"
    },

    ...
}

npm run build を実行

npm run build

asset index.js 2.14 KiB [emitted] (name: index) 1 related asset
./src/index.ts 225 bytes [built] [code generated]
./src/classes/clazz.ts 291 bytes [built] [code generated]
webpack 5.87.0 compiled successfully in 4081 ms

distフォルダが作成され、中にindex.jsが配置される

manifest.jsonの作成

Chrome拡張機能の設定ファイル、manifest.jsonをdistの中に作成する

dist/manifest.json

{
  "manifest_version": 3,
  "name": "test extension",
  "description": "実験的に作成",
  "version": "1.0",

  "content_scripts": [{
    "matches": [ "https://www.yahoo.co.jp/" ],
    "js": [ "index.js", "second.js" ]
  }]
}

"matches"に指定したURLにアクセスすると、"js"に指定したスクリプト、"css"に指定したcssを読み込む。cssは無くても良い。

cssを指定した場合はcssをdistに配置する
dist/index.css

.test-button {
  position: absolute;
  left: 0;
  top: 0;
  width: 500px;
  height: 100px;
}

Chrome拡張機能として取り込む

Chromeの「拡張機能を管理」を開く

右上の「デベロッパーモード」をONにする

左上の「パッケージ化されていない拡張機能を取り込む」から、distフォルダを指定

実行確認

yahooを開くと アラートが出てbuttonタグが追加される


vranometria