Aikの技術日記

技術的な進捗とか成果とかを細々と投稿するブログです。時々雑記も。

Electron触ってみた

はじめに

こんにちは、筆者です。

最近またもやお仕事に余裕が出てきだし、ようやく趣味プログラミングに精を出せる様になりました。
そんなわけで、何か1つ新しい技術に手を出そうかなと「Electron」に手を伸ばしてみることに。
これまで(ほぼ)Webプログラミングしかやったことなかったので、デスクトップアプリを作るのは初めてで…いろいろ学べそうです。

今回の記事では「Electronの概要」と「最小構成のElectronプロジェクトを動かしてみた経緯」などを述べていけたらと。
それではいきましょう。

Electronの概要

まずはElectronの概要から。

ElectronはGithub社が開発した、オープンソースのソフトウェアフレームワークとのことです。
プロジェクトはGithub上で管理されており、リポジトリはこちらにあります: github.com

元々は、これもGithub社が作成したエディタ「Atom」のために作ったそうです。
旧称が「Atom Shell」だったことからもそのことが伺えますね。ソース

2013年にv0.1.0がリリース。
執筆当時(2021/02/02)の最新リリースはv9.4.2となっています。

ちなみに、Electron公式サイトでのElectronの説明は下記の様になっています:

Electron は、JavaScript、HTML、CSS でデスクトップアプリケーションを作成できるフレームワークです。
これらのアプリケーションは、macOSWindowsLinux 上で直接実行したり、Mac App StoreMicrosoft Store 経由で配布したりできます。
一般的には、各オペレーティングシステム (OS) 固有のネイティブアプリケーションフレームワークを使用して、オペレーティングシステム向けのデスクトップアプリケーションを作成します。
Electron では、既知の技術で一度書くだけでアプリケーションを作成できます。

Quick Start Guide | Electron より

どうやらデスクトップアプリを作れるだけでなく、App Storeに配布もできる様ですね。
ただ、「デスクトップアプリケーション」とある様にiOSやAndroidOSなど、スマホ向けのアプリケーションは作成できません。
iOSやAndroidOSで似た様なことを行いたい場合は、Meteorを検討してみるといいかもです。
※両者の違いについて気になる方はこちらを参照に

さてこのElectronですが、採用実績には非常に有名なサービスがいくつも挙げられています。
Visual Studio Code」や「Twitch」「Microsoft Teams」など名だたる陣営。(参考: Electron公式
また、公式ページには実例として乗ってませんでしたが「Slack」にも使われているとのことです。ソース

なお、Electronは内部的には「Chromium」と「Node.js」を使用しています。このためNode.jsがない環境下だと開発ができません。

ちなみに、Electronの様な「Webフロントエンド系の技術を用いて、複数のOS向けにアプリを作成できるツール」として有名な物に「NW.js」もあります。
https://n.js .io/n.js .io

元々は「Node-webkit」という名称だったものがNW.jsに変わったものらしく。
NW.jsもといNode-webkitの方が2年ほど古株の様です。

これら2つの違いですが、下記の記事にとてもわかりやすくまとめられていた表があったので引用させていただきます:
コラム:ElectronとNW.js-マンガで分かる JavaScriptプログラミング講座

相違点 Electron NW.js
エントリーポイント index.js(JavaScriptファイル) index.html(HTMLファイル)
index.htmlを開く手順 起動後index.jsを実行(メインプロセス)。
起動後すぐにWebKitでindex.htmlを開く。
メインプロセスからWebKitを利用してindex.htmlを開く(レンダリングプロセス)。
起動後すぐにWebKitでindex.htmlを開く。
特性 1から堅牢なアプリを開発するのに向いている。 1枚ペラの、WebアプリをEXE化するのに向いている。

お次は「最小構成のElectronプロジェクトを動かしてみた経緯」について見ていこうかと。

最小構成のElectronプロジェクトを動かしてみた

今回は下記の様な流れでやっていきました:

  • Electronのインストール〜サンプルプログラム起動
  • パッケージング化のテスト
  • TypeScript化

また、おまけとして「ボイラープレート(テンプレート)を使用したTypeScript-Electronプログラム起動」も乗っけています。
こちらは「最小構成のElectronプロジェクト」ではないですが、ElectronのTypeScript開発を行う上で非常に便利だったので…ついでに紹介させていただければと。

それでは最初から順に見ていきましょう。

Electronのインストール〜サンプルプログラム起動

まずはElectronのインストールから行っていきます。

とは言ってもElectronはNPMモジュールとしてインストールできるので…。
適当なディレクトリにyarn initpackage.jsonを生成し、そこからyarn add -D electronで完了です。

お次はサンプルプログラムを起動してみます。
Electronは最小構成であれば、JavaScriptとHTMLファイル1つずつで動きますので…サンプルリポジトリを持ってくる方式ではなく、自分でこれらファイルを作る方式で行きました。

package.jsonに以下を記述し:

  "scripts": {
    "start": "electron main.js"
  },

ルートディレクトリにmain.jsindex.htmlを配置します。
コードの中身はこちらのElectron公式チュートリアルを参照しました。

あとはyarn startを実行し、こんな感じの画面が出ればOKです。 Electronアプリのスクリーンショット

パッケージング化のテスト

ローカル環境での起動確認ができたので、お次は「作成したコードをアプリケーション化する」のをやっていきます。
(「パッケージング」というらしいですね)

Electronのパッケージングには下記の3通りの方法があるのですが:

  • electron-forge
  • electron-builder
  • electron-packager

現状最もモダンなツール(らしい)かつ、公式ドキュメントのクイックスタートにも使用されていたelectron-forgeを使用することにしました。
この3つについては余談として詳しくまとめてみたので、もしよければ。

まずは、electron-forgeをするための準備としてnpx @electron-forge/cli importを実行します。
そうすると、package.jsonに下記の様にパッケージング用のコマンドが追加される(ついでにそれに必要なモジュールも追加される)ので…。

  "scripts": {
    "start": "electron-forge start",
    "clear": "rimraf node_modules",
    "package": "electron-forge package",
    "make": "electron-forge make"
  },

あとはyarn makeと叩けば、アプリケーションが生成されます。
Mac OS環境下であれば、出来上がったアプリケーションはout/[package.jsonのnameにある文字列]/[package.jsonのnameにある文字列]-darwin-x64内にあります。
VSCodeだと、アプリケーションがディレクトリとして認識されるのでFinder or Explorerで開いてください。
出来上がったアプリケーションを開き、先ほどローカルで実行した物と同じウィンドウが開けば成功です。

ちなみに…。
上記の方式で行うと、パッケージングは「コマンドを実行したマシンに最も適合した設定」で出力されます。
設定項目は「OS」と「CPUアーキテクチャ」の2種類から指定されます。筆者の環境だと「Mac OS」×「x64」で出力されました。

この辺の設定周りについては余談の章に書いたので、よければ参考までに。
…ちなみにMac OS CatalinaでElectronのWindowsOS向けパッケージングを行うのは、非常に骨が折れる作業なのでお気をつけて。
(wineがね…)
もしできた方は手順を教えてもらえると嬉しいです…。

TypeScript化

パッケージング化も出来たところでいよいよ作り始め…の前に、折角なのでTypeScript化しちゃいます。

下記の記事を参考にTypeScript化していきました。
Electron の TypeScript で Hello world - しっぽを追いかけて

やることとしては下記の通りです:
やること自体は多いですが、1つ1つはそこまで大変な作業ではありません。

  • 準備
    • TypeScript用のビルドコマンドをセットアップ
    • TypeScriptを導入
    • tsconfig.json作成
  • コードのTypeScript化
準備

まずは準備から。
「TypeScriptのビルド用コマンド」をセットアップします。
具体的には、package.jsonscriptの値を下記の様に書き換えます。

  "scripts": {
    "build": "tsc",
    "start": "yarn build && electron-forge start",
  },

その後、グローバル環境にTypeScriptを導入します。
yarn global add typescript

あとはtsconfig.jsonを作成すれば完了です。
tsc --initと叩けば、ジェネレータが勝手にtsconfig.jsonを出力してくれます。

コードのTypeScript化

お次はコードをTypeScript化していきます。
…とはいえ、main.jsのファイル拡張子をmain.tsにするだけですが。

ちなみに、TypeScriptになったおかげでimport構文が使える様になります。
なので、main.jsに記載されていた下記の記述を:

const { app, BrowserWindow } = require("electron");

import構文を使った下記の記述に変えちゃいましょう。

import {app, BrowserWindow} from 'electron'

再度yarn startを実行し、Electronのインストール〜サンプルプログラム起動にて出てきた画面と同じ画面が出てくればOKです。

ボイラープレートを使用したTypeScript-Electronプログラム起動

ここまででElectronの最小構成のビルドについては確認できましたが…。
main.tsと`index.html`しかない中、フォルダ構成などのベストプラクティスもわからず無闇に開発するのはちょっと怖いです。

そうなったときには、ボイラープレートを使用してElectronプロジェクトを作るといいかと思います。
折角なので、本章にてボイラープレートを使用して改めてElectronプロジェクトを作っていこうかと。

先に作ったElectronプロジェクトとは別のディレクトリに移動し、下記のコマンドを打ちます。
Electronプロジェクト名が、そのままpackage.jsonnameの値になります。

yarn create electron-app [ELectronプロジェクト名] --template=typescript-webpack

実行すると下記の様なフォルダ&ファイル群が生成されます。

- node_modules
- src
  - renderer.ts: Electronのレンダリング
  - index.ts: Electronを起動
  - index.html
  - index.css
- .gitignore
- webpack.main.config.js: index.tsのwebpack設定
- webpack.renderer.config.js: renderer.tsのwebpack設定
- webpack.rules.js: index.ts,renderer.ts共通のwebpack-rules設定
- webpack.plugins.js: index.ts,renderer.ts共通のwebpack-plugin設定
- tsconfig.json
- .eslintrc.json
- yarn.lock
- package.json

webpackの設定ファイルまで出力してくれる他、node_modulesのセットアップ、.eslintrc.jsonまで導入してくれます。
webpackの設定はいつも迷うのでありがたいですね…。

ちなみにpackage.jsonを覗いてみると、下記のようにwebpackの設定を行なっている記述が見えます。

{...
  "plugins": [
    [
      "@electron-forge/plugin-webpack",
      {
        "mainConfig": "./webpack.main.config.js",
        "renderer": {
          "config": "./webpack.renderer.config.js",
          "entryPoints": [
            {
              "html": "./src/index.html",
              "js": "./src/renderer.ts",
              "name": "main_window"
            }
          ]
        }
      }
    ]
...}

entryPointshtmlには「ElectronにてViewとして使用されるHTMLファイルパス」が、jsには「Electronにてレンダリングに使用されるTypeScriptファイルパス」が格納されています。
もしこれらのファイル名を変更した時は、ここも修正しないとエラーとなりますので注意を。

ちなみにReact環境やVue環境を整えたい場合は、専用のボイラーテンプレートもある様です。

こちらは先の様にコマンドで叩くのではなく、上記のGitリポジトリをcloneして使う形式の様です。

もしくはVueだと、既存のVueプロジェクトにvue add electron-builderとすることでElectronプロジェクト化できるようです。
Reactでも同じようなことができそうですね。

おわりに

今回の記事では、最小構成のElectronプロジェクトやボイラープレートを使用したElectronプロジェクトの作成方法について見ていきました。

最後に、余談として本筋とはあまり関係ない下記の知識についてまとめています。

  • Electronのパッケージ化ツールについて
  • electron-forgeの設定について

タイトルを見て気になった方はぜひ。
それでは|д゚*)

余談:Electronのパッケージ化ツールについて

#パッケージング化のテストで述べたように、Electronのパッケージ化(デスクトップアプリケーション化)の方法には以下の3通りがありますが…:

  • electron-forge
  • electron-builder
  • electron-packager

筆者的にはどれがなんだかよくわからなかったので、3つの違いについていろいろ見てみました。

こちらの記事にわかりやすくまとまってたので引用させていただくと:
[WIP]Electronつかってみた - Qiita

  • electron-builder: packagerとbuilderの両方の機能があるが、まだ開発中らしい。
  • electron-forge: インストーラを生成できる。
  • electron-packager: platform別の実行ファイルを生成できる。electron-forgeに移行する予定のようだ。

…とのことです。
また、electron-packagerは上記2つが出る前に使われていたツールらしいです(electron-forgeに移行する予定らしい)。
そのためか、Electron公式Docsにはelectron-packagerの項は見当たりません…。

ここからは本技術の注目度という観点で見てみましょう。
まずはGithubのStar、Watch数から。
※執筆当時(2021/02/05)時点のデータです

名称 Star数 Watch
electron-forge 4.1k 71
electron-builder 10.2k 157
electron-packager 7.5k 143

electron-builderが圧倒的ですね…。
対して、electron-forgeはそこまでではないようです。

npm trendsにてnpmモジュールの使用率も見てみましょう。 npmモジュールの使用率グラフ(引用: npm trends)

electron builder vs electron forge vs electron package | npm trends の執筆当時(2021/02/05)時点の累計データです

全ての期間を通してみても、electron-builderの人気は高いですね…。

Google Trendsにて検索回数をみても、順位的には大体合ってる感じです。 Google Trendsの検索回数(引用: Google Trends)

electron builder vs electron forge vs electron package | npm trends の執筆当時(2021/02/05)時点過去5年間のデータです

人気度としてみると、electron-builder>packager>forgeの順…という感じでしょうか。
electron-packagerは移行予定の物ということから、今後は徐々に下がっていくかもですね。

もっと3者を比較したい!という場合は、こちらのサイトが非常にわかりやすくまとめられていたので参考までに。
NPMCompare.com - Comparing electron-builder vs. electron-forge vs. electron-packager

余談:electron-forgeの設定について

electron-forgeでは、「OS」と「CPUアーキテクチャ」を指定することで任意のOS向けにパッケージングができます。
設定できる項目は下記の通り:
※electron-forgeは、内部ではelectron-packagerを使ってるため、設定値はelectron-packagerのドキュメントを参考にできます

例えば「WindowsOSの64bitアプリケーションを作りたい」となったらelectron-forge make --platform=win32 --arch=x64と叩けば出力できます。

ちなみに、npx @electron-forge/cli importを実行した際、package.jsonには「electron-forgeの設定」も追記されます。
こんな感じで…:

  "config": {
    "forge": {
      "packagerConfig": {},
      "makers": [
        {
          "name": "@electron-forge/maker-squirrel",
          "config": {
            "name": "[package.jsonのnameの値]"
          }
        },
        {
          "name": "@electron-forge/maker-zip",
          "platforms": [
            "darwin"
          ]
        },
        {
          "name": "@electron-forge/maker-deb",
          "config": {}
        },
        {
          "name": "@electron-forge/maker-rpm",
          "config": {}
        }
      ]
    }
  }

MacOS環境下で行った場合、platformsdarwinが指定されているのがわかるかと。

なお、完全に蛇足とはなりますが…。
OSにMac OSを指定しパッケージング化した時、パッケージング化後に出力されるアプリケーション格納フォルダ名がmacOsではなくdarwinとなっているのは…。
Mac OSの基礎OSがDarwin(ダーウィン)だからっぽいですね。

このOSはiOSの基礎ともなっているようです。Wikipediaにいろいろ詳しく載ってたので、興味あれば。
https://ja.wikipedia.org/wiki/Darwin_(%E3%82%AA%E3%83%9A%E3%83%AC%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0)