【Chrome拡張】Plasmoを利用する際の (個人的な) 初期設定

# Plasmoとは

https://github.com/PlasmoHQ/plasmo

ブラウザ拡張機能を作成するための、Reactベースのフレームワークです。
公式によると「ブラウザ拡張機能のNext.jsのようなもの」とのことです。

# 結論: Plasmoを利用する際の初期設定
## `tsconfig.json` を書き換える

まずは、以下のようにTypeScriptの設定を変更します。

```diff
   "compilerOptions": {
     "paths": {
       "~*": [
-        "./*"
+        "./src/*"
       ]
     },
-    "baseUrl": "."
+    "baseUrl": "src",
+    "strict": true,
+    "skipLibCheck": false,
+    "allowJs": false,
+    "forceConsistentCasingInFileNames": true,
+    "moduleResolution": "Bundler",
+    "noUnusedLocals": true,
+    "noUnusedParameters": true,
+    "isolatedModules": true,
+    "verbatimModuleSyntax": false,
+    "noUncheckedIndexedAccess": true
   }
 }
```

## ディレクトリ構成を変更する

機能ごとにディレクトリを分けたいので、構成を変更しておきます。

```shell
# srcディレクトリ配下にソースコードを配置していく
mkdir src
cd src

# Background, コンテンツスクリプト, ポップアップ用のディレクトリを作成
mkdir background contents popup

# React用のディレクトリを作成
mkdir components hooks

# 既存のpopupファイルを移動
mv ../popup.tsx popup/index.tsx
```

# 補足: `tsconfig` の変更内容について
## Plasmoの `tsconfig.base.json` の設定を上書きする

`tsconfig.base.json` は以下のような内容になっています。
TSを書いていく上でこのままの設定だと辛い部分がありそうなので、設定を変えておきます。

```json:tsconfig.base.json
{
  "$schema": "https://json.schemastore.org/tsconfig",
  "display": "Plasmo Extension",
  "files": ["./plasmo.d.ts"],
  "compilerOptions": {
    "strict": false,
    "skipLibCheck": true,

    "target": "esnext",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "incremental": true,
    "esModuleInterop": true,
    "module": "esnext",
    "resolveJsonModule": true,
    "declaration": false,
    "declarationMap": false,
    "inlineSources": false,
    "moduleResolution": "node",
    "noUnusedLocals": false,
    "noUnusedParameters": false,
    "preserveWatchOutput": true,

    "verbatimModuleSyntax": true,
    "jsx": "preserve"
  }
}
```

### `compilerOptions` を見る

現状設定されているオプションの概要と、変更の必要性について確認していきます。

- strict
	- `true` に設定すると、厳密に型チェックしてくれるようになります
	- `strict: false` でTypeScriptを書いていくことは、TypeScriptの型の恩恵を捨てていることと同義ですので、**必ず `true` にしましょう**
- skipLibCheck
	- `true` に設定すると、`*.d.ts` ファイルに対する型チェックがスキップされるようになります
	- 厳密性と速度のトレードオフになりますので、プロジェクトの規模にもよって判断は変わるかと思います
	- 厳密にしたいので `false` にしましょう
- target
	- トランスパイルするJavaScriptのバージョンを指定します
	- このままにします
- lib
	- TypeScriptを書く際に利用できる機能を指定します
	- 今後実装する機能によっては追加が必要かもしれません
	- 一旦このままにします
- allowJs
	- `true` に設定すると、 `.js` や `.jsx` もコンパイル対象となります
	- 基本的にtsオンリーで書いていきたいので `false` にしましょう
- forceConsistentCasingInFileNames
	- `true` に設定すると、実行しているファイルシステムの大文字小文字を区別するルールに従わないimport文にはエラーを出すようにします
	- `true` のままにします
- noEmit
	- `true` に設定すると、トランスパイル結果を出力しなくなります
	- Plasmoは内部でParcelというバンドラーを利用しており、tscでJSにトランスパイルするわけではないため `true` のままにします
- incremental
	- `true` に設定すると、前回のトランスパイルと比較して変更があった差分のみをトランスパイルするようになります
	- `true` のままにします
- esModuleInterop
	- `true` に設定すると、CommonJSなどのモジュールをES6形式でインポートできるようになります
	- `true` のままにします
- module
	- モジュールパターンを指定します
	- このままにします
- resolveJsonModule
	- `true` に設定すると、JSONの形式から自動的に型定義を抽出できるようになります
	- `true` のままにします
- declaration
	- `true` に設定すると、トランスパイルした各tsファイルに対してexport型定義ファイルを生成する
	- `false` のままにします
- declarationMap
	- `true` に設定すると、型定義のmapファイルを生成します
	- `declaration` が `false` だと特に設定する意味がないので、そのままにします
- inlineSources
	- `true` に設定すると、元のtsファイルの内容を文字列としてソースマップ内に埋め込みます
	- `false` のままにします
- moduleResolution
	- バンドラーを利用しているので `node` から `Bundler` に変更しましょう
- noUnusedLocals
	- `true` に設定すると、利用していない変数宣言を禁止します
	- `true` にしましょう
- noUnusedParameters
	- `true` に設定すると、関数で利用していない引数を禁止します
	- `true` にしましょう
- preserveWatchOutput
	- `true` に設定すると、watchモードで変更があった際に以前のコンソール出力を残したままにするようになります
	- `true` のままにします
- verbatimModuleSyntax
	- `true` に設定すると、トランスパイル時にimport文の構文を維持してくれますが、CommonJSとは相性が悪いです。
	- `false` にしましょう
- jsx
	- JSXの変換ルールを設定します
	- このままにします

### 足りない設定を考える

以下の設定も追加しておきます。

- isolatedModules
	- `true` に設定すると、各ファイルを独立して変換する際に、解釈できないコードがある場合にはエラーを出します
- noUncheckedIndexedAccess
	- `true` に設定すると、インデックス型のプロパティや配列要素を参照したときundefinedのチェックを必須にします