Electronやってみたかった

# Electronやってみたかった
HTMLやCSSを使ってデスクトップアプリが作れる！？アツい！
そんな勢いでどのようにハウトゥーしたのか、軽くご紹介したいと思います。

# とは？
Electronとはなんでしょう？

- HTML + CSS + JavaScriptとかのフロントのWeb技術でデスクトップアプリを作成できるフレームワーク。Reactとかもいける。
- Visual Studio CodeやAtomといったコードエディタや、Slackのデスクトップ版で利用されています。
- 内部的にはChromeの元となったChromiumがランタイムとして動いているので、古代のインターネットエクスプフンフンとかナントカーフォックスとかのブラウザの違いを意識しなくても、Chromeでだけ動くように開発すればよい。タノシイ。
- Chromeに搭載されている開発者ツールがそのまま使えるので、フロントの開発になれた方にはかなりやりやすいかと思います。

# 必要なもの
大体6ステップで動いちゃうので、ペロっと見てみましょう。
### 1. プロジェクトを開始する
まずはプロジェクトを開始しちゃいましょう。

```
npm init
```

マッスルメモリーが過ぎてもはや左足の薬指でもタイプできますね。

### 2. Electronをインストールする
ではElectronちゃんをプロジェクトにインストールしましょう。

```
npm install electron
```

もはや説明は必要ないでしょう。
単語数が増えた分左足の親指といったところでしょうか。
グローバルインストールする必要はあまりないかと思います。

### 3. エントリポイントを指定する
Electronちゃんが起動したときに、どのファイルから実行するべきか
迷子にならないようにエントリーポイントを指定します。
1.で生成されたpackage.jsonに

```
"main": <エントリポイントにしたいJSファイル.js>
```

を追記します。これだけなんですけどね。
公式チュートリアル的にはmain.js推しのようなので、
新しいソフトをインストールするときもハイハイと音速で続行ボタンを押しちゃう私みたいな方はとりあえずmain.jsにしておきましょう。
俺はいつだってカスタムインストールだぜって方は面白ファイル名にしておきましょう。

### 4. main.jsを書く
ここからプログラマっぽいことをします。
3.でエントリポイントに指定したファイル名で、JavaScriptを書きます。
今回はmain.jsにしたので、この名前でいきます。
コメントで解説してる風ですが、大体公式チュートリアルです。

```
　// electronからappとBrowserWindowをインポートする。
const { app, BrowserWindow } = require('electron')
  
 　 // 変数winにウィンドウオブジェクトを代入していきますが、グローバルにアクセスできるところに置いておかないと
  　// JavaScriptがよしなにガーベジコレクションしてくれる際にせっかく作ったウィンドウをよしなに閉じまくっていきます。
  let win
  
  // ウィンドウを生み出すファンクションを作ります。
  function createWindow () {
   　 // 先にインポートしたBrowseWindowにオプションを渡してnewすると、ウィンドウオブジェクトが生成されます。
   　 // 今回は触れませんが、ここで渡すオプションによって半透明になったりボーダーレスになったりして楽しいです。
    win = new BrowserWindow({ width: 800, height: 600 })
  
    　// Electronを使う理由といっても過言ではありません。生成したウィンドウオブジェクトに表示するhtmlファイルを指定します。
   　 // loadFile()した時点でウィンドウが表示されるようです。
    win.loadFile('index.html')
  
   　 // 開発者ツールみせろ！インスペクトさせろ！という方ははじめから開発者ツールを開いておくことも出来ます。
    win.webContents.openDevTools()
  
   　 // ウィンドウが閉じられた際のイベントリスナーを設定します。基本的にはウィンドウを閉じたら変数をnullにすればグッドです。
    win.on('closed', () => {
      win = null
    })
  }
  
 　 // ついに上のファンクションを実行します。後述しますがインポートしたBrowserWindowはウィンドウを制御し、
　  // appはElectronアプリの大元のプロセスを管理します。appひとつですが、複数のウィンドウを同時に立ち上げることもできます。
 　 // Electronアプリ自体が初期化完了すると、createWindowファンクションが実行されます。
  app.on('ready', createWindow)
  
 　 // 立つ鳥跡をアレせず。ウィンドウがすべて閉じられたら大元のプロセスも終了しましょう。
  app.on('window-all-closed', () => {
　　　// おしゃれmacOSをお使いの方は、windowsとウィンドウの挙動が異なっているので、
  　  // プラットフォームがおしゃれdarwinの場合はおしゃれにquit回避しましょう。
    if (process.platform !== 'darwin') {
      app.quit()
    }
  })
  
 　 // 続けておしゃれmacOSの方専用のイベントです。
  app.on('activate', () => {
 　　  // macOSでは他のウィンドウが開いていないときにドックアイコンをクリックして
  　  // ウィンドウを再生成することがあるので、再びcreateWindowファンクションを呼び出します。
    if (win === null) {
      createWindow()
    }
  })

```

### 5. html書く

ここまでくれば大体終わりです。
上のmain.jsでは既に読み込んだことになっていますが、生成されるウィンドウで読み込むhtmlファイルを作成しましょう。
空のhtmlファイルでも良いのですが、とりあえずチュートリアルのものをコピペしましょう。

```
<!DOCTYPE html>
  <html>
    <head>
      <meta charset="UTF-8">
      <title>こんにちは世界</title>
    </head>
    <body>
      <h1>こんせか</h1>
      node.jsのバージョン: <script>document.write(process.versions.node)</script>,
      Chromeのバージョン: <script>document.write(process.versions.chrome)</script>,
      Electronのバージョン: <script>document.write(process.versions.electron)</script>.
    </body>
  </html>
```

ここでHTML+CSS+JavaScriptでApple顔負けの爆裂におしゃれ画面を作ることも出来ちゃいます。
\<script>タグで囲めばスクリプトの実行も可能ですし、外部スクリプトを読み込むことも出来ます。


#### 謎のハマりポイント！ ～～jQueryの逆襲～～
jQuery使いたいやん、jQueryでまだいけるやん、と、作成したHTML上で

```
<script src='jQuery.js'></script>
<script src='jQuery使ったスクリプト.js'></script>
```

とかやっても、
> $ is not defined

とか言われて泣きそうになります。ジェクエリ先に読みこんどるやん！
あわてず騒がずこちらの記事
https://qiita.com/pirosikick/items/72d11a8578c5c3327069
を読んでありがたく

```
<script>
window.jQuery = window.$=require('jQuery.js');
</script>
```

に書き換えましょう。

### 6. 実行！
完成しました。ではプロジェクトディレクトリでおもむろに

```
npx electron .
```

しましょう。スゴイ！
ここまででHTMLで作られたウィンドウが素敵に表示されるはずです。

## パッケージ化
Electronちゃんなら作成したアプリを簡単にパッケージ化して配布することも出来ちゃいます。
別途electron-packagerをnpm installして、

```
npm install electron-packager -g
```

ルートディレクトリとイカしたアプリ名、プラットフォームを指定します。

```
electron-packager <ルートディレクトリ(直下なら.)> <アプリ名> --platform=<プラットフォーム>
```

プラットフォームには、
- windowsであれば"win32"
- macOSであれば"darwin"
- Linuxであれば"linux"
を指定すれば、それぞれのOSで実行できるexeファイルを生成してくれます。

※この方法でパッケージ化すると、作成したjsファイルやhtmlファイルなどは読める上体でresourceディレクトリに入るので、やましいファイルは別途asar形式で圧縮する必要があります（やってない）

# アーキテクチャ
Electronのプロセスは、メインプロセスとレンダラープロセスに分けられます。

メインプロセスは、平たく言うとエントリーポイントで実行されるjsファイル、今回の場合はmain.jsで、appモジュールを利用していたものです。
メインプロセスはElectronアプリ1つに対して必ず1つ存在していなければいけません。

対してレンダラープロセスは、メインプロセスでBrowserWindowをnewした際に生成されるプロセスです。こちらは各ウィンドウで行われる処理、すなわちhtmlファイルとそれが読み込むjsファイルなどが含まれます。
レンダラープロセスはウィンドウの数と一致するので、好きなだけ生成することができます。
また、注意点としてレンダラープロセスで重たい処理を行うと、Chromiumで実行するのと同じなので、動作が停止することがあります。
重たい処理はremote等の仕組みを使ってメインプロセスで実行しましょう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/279581/443dcb97-7bdc-b99d-5818-4e4c239b9ef1.png)
https://www.oreilly.com/library/view/introducing-electron/9781491996041/ch01.html#the_two_electron_process_types


# 参考
- https://electronjs.org/docs/tutorial/first-app
- https://qiita.com/pirosikick/items/72d11a8578c5c3327069
- https://www.oreilly.com/library/view/introducing-electron/9781491996041/ch01.html#the_two_electron_process_types