ElectronアプリをTypeScriptとReactで作成する


# 概要
Mac上でelectronアプリを開発するにあたり、まず以下の構成での最小限アプリを作り動作検証を行った。

# 構成
- Macintosh (Catalina ver10.15.7)
- node.js (ver12.13.0)
- electron (ver13.1.8)
- typescript (ver 4.0.2)

# 成果
- ボタンをクリックするとカウントアップする単純なelectronアプリを構築
- TypeScript で記述したアプリコードの中でブレークポイントを設定してChromium 内蔵デバッガで停止できることを確認
- react developer tools により、react component tree を Chromium 内蔵デバッガで表示できることを確認

# 構築手順

## node.js 開発環境

参照: [nodebrewでnodeのバージョンを切り替える方法 - Qiita](https://qiita.com/kuriya/items/36ae29366df0b7c95dec) 

Mac 上では nodebrew を使って node.js をインストールしておくとよい。今回は ver12.13.0 を利用する。

```
$ node --version
v12.13.0
```

## Electron (with TypeScript + Webpack) 開発環境

参照： [TypeScript + Webpack - Electron Forge](https://www.electronforge.io/templates/typescript-+-webpack-template)

ここでは、今後作ってみるつもりの world clock のためのプロジェクトを作る手順を示していく。
自動生成された Hello World が動作することが確認できる。

```
$ yarn create electron-app world-clock --template=typescript-webpack
$ cd world-clock
$ yarn start
```

![dumb-typescript-template.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1861827/fe0bf534-4eb1-9522-bbd9-41c371292589.png)

## React の導入

参照： [React with TypeScript - Electron Forge](https://www.electronforge.io/guides/framework-integration/react-with-typescript)

変更手順の詳細は上記のリンク先を参照。以下のようなファイル構成とした。

```
world-clock/
  +-- README.md
  +-- tsconfig.json                  // JSX サポートを追加
  +-- package.json                   // react, react-dom を追加
  +-- yarn.lock
  +-- webpack.main.config.js         // webpack.* は、自動生成されたまま
  +-- webpack.plugins.js
  +-- webpack.renderer.config.js
  +-- webpack.rules.js
  +-- node_modules/
  |     +-- ....
  +-- src/
        +-- index.ts                 // main process で実行される
        +-- index.html               // ほぼ白紙
        +-- renderer.ts              // renderer process で最初に実行される preload script
        +-- App.tsx　　　　　　　　　　　// react
        +-- DumbButton.tsx           // react
```

ここで実行をすると、以下のようにボタンを押すとカウントアップする electron アプリが起動される。

```
$ yarn start
```

![count-up-app.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1861827/4caad4d9-9efa-b6f4-a289-8261a7e25bdc.png)

# コード詳細

コード中でポイントとなる部分を説明しておく。gitlab 上のソースコードは[こちら](https://gitlab.com/ken.miyasita/world-clock/-/tree/branch-0.0.1)。

## index.ts

参照： [GitHub - MarshallOfSound/electron-devtools-installer: An easy way to ensure Chrome DevTools extensions into Electron](https://github.com/MarshallOfSound/electron-devtools-installer)

今後の開発の中で　react developer tools を使いたいので、electron-devtools-installer を利用することにした。この仕組みにより、renderer process を担う chromium 起動時に指定した拡張機能（今の場合 react developer tools）を自動インストールできる。

```typescript:index.ts
import installExtension, {
  REACT_DEVELOPER_TOOLS,
} from "electron-devtools-installer";

app.on("ready", () => {
  // For now, I would use React Dev Tools.
  installExtension(REACT_DEVELOPER_TOOLS)
    .then((name) => console.log(`Added Extension:  ${name}`))
    .catch((err) => console.log("An error occurred: ", err));
});

```

## renderer.ts

参照： [TypeScript + Webpack - Electron Forge](https://www.electronforge.io/templates/typescript-+-webpack-template)

今回利用したテンプレートでは、renderer.ts というファイルがrenderer process で最初に実行される preload scriptとして指定されている。この renderer.ts に react の JSX 記法を直接記述しようとすると、ファイル名を renderer.tsx に変更する必要があり話が面倒になる。

よって、以下のように実際の react (with JSX) の記述は　App.tsx から先のファイル群で行うとし、この renderer.ts はシンプルな1行とした。

```typescript:renderer.ts
import "./App";
```

## App.ts, DumbButton.ts

ごく普通のサンプルコードで、取り立てて説明する箇所はない。gitlab 上のコードを参照。

- [App.ts](https://gitlab.com/ken.miyasita/world-clock/-/blob/branch-0.0.1/src/app.tsx)
- [DumbButton.ts](https://gitlab.com/ken.miyasita/world-clock/-/blob/branch-0.0.1/src/DumbButton.tsx)

今後の開発、デバッグにおいて大事な2つの点を確認した。

(1) Chromium 上のデバッガが利用できること

react を使うということはアプリケーションコードのほとんどが renderer process 上で動くので、renderer process のデバッグがスムーズにできることを確認したい。
ボタンをクリックしたときに起動される onClick() にブレークポイントを設定すると、クリック時にきちんと止まることが確認できた。

![debug.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1861827/9f78cd69-964d-ab2e-e02e-d238da198ec9.png)

(2) react developer tools が利用できること

今回は、この確認のためにあえて App, DumbButton という2つの react component を作成した。
react component tree が構築され、react developer tools がその構造に基づいた情報を表示していることが確認できた。

![react-dev-tools.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1861827/4b68e3c4-12c9-7089-0fa2-3176b5394ee0.png)