electron-react-boilerplateのpackage.jsonを理解する


electronのボイラープレートの中でもシェアが高く使い勝手の良いelectron-react-boilerplate
https://github.com/electron-react-boilerplate/electron-react-boilerplate

typescriptビルド環境からreact/redux react-routerなどのライブラリ群も入っていて尚且つテストツールやpre-commitまで入って至れり尽くせり。
そのまま使えばリッチな環境で開発が行えるが故に、定義ファイル群を理解せずに使いがち
あれこれディレクトリ構成を変えてるうちに動かなくなった なんてことにならないように一つ一つ読んで理解していこうと思う。

この記事ではpackage.jsonに書かれている定義から読み解いていく。

# この記事で書かないこと
「electron-react-boilerplateの」package.jsonの機能的な部分だけに触れていくので以下のようなpackage.json自身のフィールドには触れない
repository, author contributors, license, bugs, keywords, homepage ...etc

electron-builderだとか、pre-commitなど拡張されたフィールドについて見ていく。

# package.jsonに書かれているフィールド
package.jsonの定義を一つ一つ見ていく
## lint-stagedフィールド
```json
  "lint-staged": {
    "*.{js,jsx,ts,tsx}": [
      "cross-env NODE_ENV=development eslint --cache"
    ],
    "{*.json,.{babelrc,eslintrc,prettierrc,stylelintrc}}": [
      "prettier --ignore-path .eslintignore --parser json --write"
    ],
    "*.{css,scss}": [
      "stylelint --ignore-path .eslintignore --syntax scss --fix",
      "prettier --ignore-path .eslintignore --single-quote --write"
    ],
    "*.{html,md,yml}": [
      "prettier --ignore-path .eslintignore --single-quote --write"
    ]
  }
```
stageされたファイルを対象にlintをかけるlint-stagedに関する定義が書かれるフィールド
Readmeを参考に読み解いていく
https://github.com/okonet/lint-staged

##### 1つ目
```json
"*.{js,jsx,ts,tsx}": [
      "cross-env NODE_ENV=development eslint --cache"
    ],
```
gitにstageされたjs, jsx, ts, tsxファイルに対してeslintを実行する

##### 2つ目
```json
"{*.json,.{babelrc,eslintrc,prettierrc,stylelintrc}}": [
      "prettier --ignore-path .eslintignore --parser json --write"
    ],
```
.eslintignoreに記載されているものを除き、jsonと各rcファイルに対してprettierを実行する

##### 3つ目
```json
"*.{css,scss}": [
      "stylelint --ignore-path .eslintignore --syntax scss --fix",
      "prettier --ignore-path .eslintignore --single-quote --write"
    ],
```
.eslintignoreに記載されているものを除き、 css, scssファイルに対してstylelintとprettierを実行してファイルを修正する

##### 4つ目
```json
"*.{html,md,yml}": [
   "prettier --ignore-path .eslintignore --single-quote --write"
    ]
```
.eslintignoreに記載されているものを除き、 html, md, ymlファイルに対してprettierを実行してファイルを修正する

## buildフィールド
```json

"build": {
    "productName": "ElectronReact",
    "appId": "org.develar.ElectronReact",
    "files": [
      "dist/",
      "node_modules/",
      "app.html",
      "main.prod.js",
      "main.prod.js.map",
      "package.json"
    ],
    "dmg": {
      "contents": [
        {
          "x": 130,
          "y": 220
        },
        {
          "x": 410,
          "y": 220,
          "type": "link",
          "path": "/Applications"
        }
      ]
    },
```
electron-react-boilerplateが内包しているビルドモジュール electron-builderの定義が書かれているフィールド
公式ドキュメントを見ながら読み解いていく
https://www.electron.build/configuration/configuration

##### productName
アプリの名前 パッケージ化した時のファイル名になる。
スペースや特殊文字は使用不可とのこと

##### appId
MacではCFBundleIdentifier、WindowsではApplication User Model IDsとして使われる文字列
アプリケーションを識別するのに使う

##### files
packageのなかに含めるリソースファイルを定義する
ビルドファイルやnode_modulesなどが含まれる

##### directories
- buildResources   -> ビルド時に使用するリソースディレクトリ名 この中に入れたファイルがアプリに含まれると言うわけではなく、含めたいファイルはfilesフィールドで定義する必要があるらしい。

- output -> パッケージ時の出力ディレクトリ名

##### dmg
Macのdmgファイルをどのように作成するかの定義
contents -> iconの表示位置などの設定 x,yはアイコンの中心位置への参照

##### win
windows用のビルドの設定項目
target -> ビルドで出力するファイルのタイプ

##### Linux
Linux用のビルドの設定項目
target -> ビルドで出力するファイルのタイプ

## jestフィールド
```json
"jest": {
    "testURL": "http://localhost/",
    "moduleNameMapper": {
      "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/internals/mocks/fileMock.js",
      "\\.(css|less|sass|scss)$": "identity-obj-proxy"
    },
    "moduleFileExtensions": [
      "js",
      "jsx",
      "ts",
      "tsx",
      "json"
    ],
    "moduleDirectories": [
      "node_modules",
      "app/node_modules"
    ],
    "setupFiles": [
      "./internals/scripts/CheckBuildsExist.js"
    ]
  },
```
テストランナーのjestの定義が書かれるフィールド
公式ドキュメントのConfigガイドを見ながら読み解いていく
https://jestjs.io/docs/ja/configuration

##### testURL
jsdom環境に与えられるURL defaultはabout:blankになっており、問題を起こすケースがあるのでlocalhostが入っている様子

##### moduleNameMapper
テストでは扱いづらい画像ファイル、フォントファイルなどのリソースをモックするための記述
画像、音声、動画ファイルなどは fileMock.js の内容でモックされる('test-file-stub'という文字列）
style関連のファイルはidentity-obj-proxyによってmockされる
https://github.com/keyz/identity-obj-proxy

##### moduleFileExtensions
使用するモジュールの拡張子を羅列する配列
公式ドキュメントによると**プロジェクトの中で一番頻度高く使用する拡張子を配列の最初に持ってくる**ことが推奨されている。
typescriptを使用するならts, tsxを配列の最初に移動した方がテストのパフォーマンスが向上するだろう。

##### moduleDirectories
モジュールが格納されているディレクトリ名の配列を指定する。defaultはnode_modulesだが、app配下にも存在するので、app/node_modulesを追加した配列を指定している

##### setupFiles
各テストファイルの実行前に実行されるスクリプトを配列で指定する
ここで指定されているCheckBuildExists.jsでは main.prod.jsとrenderer.prod.jsの２つのファイルの存在チェックを行い、存在しなければ例外をThrowしてビルドコマンドを実行するメッセージを表示している

## prettierフィールド
```json
"prettier": {
    "overrides": [
      {
        "files": [".prettierrc", ".babelrc", ".eslintrc", ".stylelintrc"],
        "options": {
          "parser": "json"
        }
      }
    ],
    "singleQuote": true
  }
```
コードの自動整形をしてくれるPrettierの定義フィールド
公式のconfigガイドを見ていく
https://prettier.io/docs/en/configuration.html

##### overrides
特定のファイルに対して異なるオプションを設定するための定義
通常prettierはファイルの拡張子からパーサーを判断してくれるが、rcファイルは拡張子がないためjsonとしてフォーマットさせる定義が書いてある
この手法はprettier公式のexampleにも書いてある

##### singleQuote
ダブルクォートの代わりにシングルクォートを使用する

## stylelintフィールド
```json
  "stylelint": {
    "extends": ["stylelint-config-standard", "stylelint-config-prettier"]
  }
```
css, scssのフォーマットチェックをしてくれるstylelintの定義　少ないけれど公式をちゃんと見る
https://stylelint.io/user-guide/configure

##### extends
継承する既存の設定ファイルの配列　**後に書いたファイルの設定が優先して適用される**

- stylelint-config-standard -> 60のルールを適用して推奨定義を拡張する
- stylelint-config-prettier -> prettierと競合する不必要なルールを無効にする

## renovate
```json
  "renovate": {
    "extends": ["bliss"]
  }
```
npmパッケージの更新を補助するrenovateの定義フィールド
https://docs.renovatebot.com/configuration-options/#extends

##### extends
継承/使用するpresetを指定するファイル
指定されている'bliss'はrenovateの介入を最小限にする設定がされているらしい
https://github.com/amilajack/renovate-config-bliss

## huskyフィールド
```json
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  }
```
gitの粗悪なcommitやpushを防いでくれるhuskyの定義フィールド
https://github.com/typicode/husky

##### hooks
何かを契機にコマンド実行するような定義をするフィールド
pre-commitはコミットの直前に動作させるコメントを定義できる
上述のlint-stagedを動作させている　failした場合はcommitできない

# 終わりに
かなりボリュームはあったが、electronに限らずモダンWeb開発でよく使われるモジュールの定義が多数書かれていた。
ここに書かれている各モジュールについて理解することはelectron-react-boilerplateに限らず、多くの開発環境を作成、利用していくために役立つ知識になるでしょう。