Electronでデスクトップアプリケーションを開発する方法
読む所要時間: 21 分
チームコラボレーションソフトウェアの定番であるSlack、本稿執筆時点で市場で最も人気のあるコードエディタの一つであるVisual Studio CodeとWhatsAppのデスクトップ版には共通点があります。それは、これらすべてがElectron.jsで構築されているということです。これらの企業が、ネイティブのデスクトップソフトウェア開発手法よりもElectron.jsを採用したことにより、Electron.jsはデスクトップアプリケーション開発のための信頼できるフレームワークとして確立されました。
本稿では、Electron.jsの概要と、そのユースケースをご紹介します。
このチュートリアルでは、以下のようなデスクトップアプリケーションを開発します。
- Web技術で一から構築されている。
- メインプロセスとレンダラープロセスの間で通信を行う。
- Electron.jsのAPIを利用し、ブラウザAPIでは利用できない機能にアクセスすることができる。
- デスクトップ通知を表示する。
Electron.jsの概要
Electron.jsを知る
Electron.jsは、HTML、CSS、JavaScriptなどのWeb技術を使ってデスクトップアプリケーションを構築するためのオープンソースフレームワークです。これにより、デスクトップアプリケーションの構築は、もはやC++、C#、Javaの開発者だけのものではなくなり、Web開発者はそのスキルを業界標準のデスクトップソフトウェアの開発に転用できるようになったのです。
Chromium(Google Chromeブラウザのオープンソース版)とNode.js JavaScriptランタイムを使うことにより、Web開発者は既存のWebアプリケーションとElectron.jsを組み合わせ、Windows、macOSおよびLinuxプラットフォーム用のデスクトップアプリケーションとインストーラーを作成できるようになっています。
Electron.jsはGithubでメンテナンスされており、強力なエンジニアチームに支えられた信頼性の高いツールです。
Electron.jsを使用する理由
Electron.jsが登場する以前は、WindowsとMacなど複数の異なるOSにインストールする場合、WindowsではC#、Visual Basic、MacではObjective-Cといったプラットフォーム互換の言語を使って、それぞれのプラットフォーム用にアプリケーションを開発しなければなりませんでした。さらには、もし開発者がJavaを使ってクロスプラットフォームのデスクトップ・ソフトウェアを開発することを選んだ場合、そのアプリケーションのユーザーは、アプリケーションを実行するために両方のプラットフォーム上にJavaランタイムをインストールする必要がありました。
しかし、Electron.jsは単一のコードベースにより、インストールに依存することなく全てのプラットフォーム用のインストーラを生成することが可能です。このため、たった1つの開発チームでも複数のプラットフォームに対応するアプリケーションを開発できます。また、Electron.jsでは、Web開発ができればデスクトップアプリケーションも構築できるため、既存のWeb開発者がデスクトップソフトウェアの開発者に容易に転身できることも大きなメリットです。
Electron.jsアプリケーションを構築するための前提条件
Electron.jsでアプリケーション開発を始めるために必要な項目は以下のとおりです。
- HTML、CSS、JavaScriptの基礎知識。
- Node.jsがインストールされていること。
- Node.jsの基本知識。
Electron.jsアプリケーションの構造
Electron.jsは構造上、大きく3つの部分から構成されています。
- Chromium: Electron.jsの構造体の中で、Webページの作成と表示を担当する部分です。WebコンテンツはElectron.jsのレンダラープロセス(詳細は後述)で表示され、Chromium環境のため、一般的なGoogle Chromeブラウザで操作するのと同様に、すべてのブラウザAPIと開発ツールにアクセスできます。
- Node.js: Electron.jsの構造体の中で、システム機能にアクセスするためのコンポーネントです。Electron.jsはNode.jsをメインプロセスで実行し、ファイルシステムやOSなどNode.jsが提供するすべての機能を利用できます。
- Custom APIs: 開発者が一般的なデスクトップ体験を作成し、ネイティブの機能で簡単に作業できるように、Electron.jsでは、コンテキストメニューの作成と表示、デスクトップ通知の表示、キーボードショートカットの操作などのタスクを実行するための使いやすいライブラリのAPIが用意されています。
メインプロセスとレンダラープロセス
Electron.jsアプリは、メインプロセスと、レンダラープロセスの2種類のプロセスを保持しています。
Electron.jsアプリケーションのエントリーポイントはメインプロセスで、これは単にNode.jsの環境となります。ここでネイティブの機能とのやり取りが行われます。
メインプロセスはウェブページを作成する役割を担っています。これは、Electron.jsのBrowserWindow
オブジェクトの新しいインスタンスを作成することで行われます。これによって、独自のレンダラープロセスで動作する新しいウェブページが作成されます。メインプロセスは複数のウェブページを作成でき、それぞれが独自のレンダラープロセスで実行されます。
通常、Electron.jsのアプリケーションはデフォルトのWebページを起動画面とします。アプリケーションで必要であれば、さらに画面を作成できます。
各レンダラープロセスは、それぞれのWebページを管理し、他のレンダラープロセスやメインプロセス自体から完全に分離されています。このため、一つのレンダラープロセスが終了しても、他のレンダラープロセスには影響しません。レンダラープロセスは、メインプロセスからそのインスタンスを破棄することによっても終了できます。
レンダラープロセスがアクセスできるのは、ブラウザのAPIであるwindow
や document
オブジェクトなどだけです。これは、レンダラープロセスが単に実行中の Chromiumブラウザインスタンスであるためです。ただし、Node.jsのAPIである process
やrequire
にアクセスできるように設定することは可能です。
メインプロセスとレンダラープロセスのコミュニケーション
Electron.jsアプリケーションでは、ユーザーがボタンをクリックするなどのイベントに応じてネイティブ機能を使いたいことがよくあります。しかし、レンダラープロセスとメインプロセスは完全に分離されているため、Webページからネイティブ機能に直接アクセスできません。
この問題を解決するために、Electron.jsではIPC(Inter-Process Communication)というチャネルを用意し、レンダラープロセスとメインプロセス、またはその逆の通信を可能にしています。
メインプロセスとレンダラープロセスにそれぞれ対応したモジュールであるipcMain
とipcRenderer
を使用すると、一方のプロセスからイベントを発信し、もう一方のプロセスのイベントをリッスンできます。また、あるプロセスから別のプロセスへデータを渡すこともできます。本稿の後半では、これらのモジュールを使用して、レンダラープロセスとメインプロセスの間で通信を行う予定です。
Electron.jsの簡単なプロジェクトの構築
それでは、Electron.jsを実際に使ってコーディングしてみましょう。本稿では、タスクリストに項目を追加する簡単なデスクトップアプリケーションを作成します。目標は、ゼロからデスクトップアプリケーションを作成し、正常に実行することです。
アプリケーションの雛型を作成する
まず、任意のディレクトリから以下のコマンドを実行して、プロジェクト用のフォルダを作成し、新しいフォルダにディレクトリを変更します。
Electron.jsのアプリケーションは、基本的にWebページを実行するNode.jsアプリケーションなので、以下のコマンドを実行してアプリを初期化し、package.jsonファイルを作成します。
次に、プロジェクトフォルダのルートにindex.htmlファイルを作成し、次のコードを追加して、アプリケーションのホームページを作成します。
上記のHTMLコードでは、タイトルに「My Electron App」、「Welcome to My Electron App」というh1
タグを含むウェブサイトが作成されます。
これで、Node.jsアプリケーションが作成できました。次のステップでは、Electron.jsを使用して、デスクトップアプリケーションに変換します。
まず、Electron.js ライブラリをインストールします。コマンドプロンプトに戻り、プロジェクトのルートディレクトリで、以下のコマンドを実行します。
インストールが完了したら、main.jsという名前のファイルを新規作成します。これは、アプリケーションへの入り口となるもので、メイン処理のスクリプトです。このスクリプトは、次のような処理を行います。
- アプリケーションのホーム画面用のウェブページを作成する。
- Electron.jsアプリの起動時にアプリのホーム画面をロードする。
- アプリケーションのウィンドウを閉じていても、アプリケーションが起動していれば、アイコンをクリックしたときにホーム画面を読み込む。
main.jsでは、まず必要なパッケージをインポートし、アプリケーションのホーム画面に新しいウェブページを作成するための関数を作成します。
上のコードブロックでは、Electron.jsパッケージからapp
(Electron.jsアプリケーションオブジェクト) とBrowserWindow
(Webページの作成と読み込みを行う Electron.jsモジュール)をインポートしています。また、プロジェクトディレクトリを操作できるようにするためのモジュールであるpath
もインポートされています。
インポートの下に、loadMainWindow()
関数があります。この関数は、プロジェクトのルートからindex.htmlファイルをロードして、1200px × 800pxの新しいブラウザウィンドウを作成するためにBrowserWindow
オブジェクトを使用します。
次に、main.jsで先程追加したコードの下に、アプリが起動した直後に関数が呼び出されるように、 loadMainWindow()
関数の呼び出しを追加します。
次のステップは、一部のOSで、すべてのウィンドウを閉じた後もアプリケーションがアクティブなままになっている問題への対処です。これは、MacOS以外のプラットフォームでよく発生します。この問題を解決するには、main.jsの既存のコードの下に、次のコードを追加します。
このコードは、メインのプロセスによって作成されたすべてのウィンドウが閉じられたときに発生するイベントであるwindow-all-closed
をリッスンするよう指示します。次にプラットフォームがMacOSであるかどうかを確認し、MacOSでない場合は明示的にアプリケーションを終了してメインのプロセスを終了させ、アプリケーションを終了します。
このファイルの最後のステップは、ウィンドウが開いていないときに、オペレーティングシステムのDockでアイコンをクリックすると、アプリケーションが起動するようにすることです。main.jsファイルの最後に以下のコードを追加します。
このコードでは、アプリケーションのactivate
イベントをリッスンします。このイベントが発生すると、現在開いているアプリケーションのウィンドウがあるかどうか確認します。開いていない場合は、ホーム画面をロードするためにloadMainWindow()
を呼び出します。
これでmain.jsファイルの作業は以上です。
アプリケーションの設定
アプリケーションがElectrion.jsで正しく動作するよう設定するために、package.jsonファイルを変更する必要があります。
package.json* ファイルを開きます。main
キーの値を以下のように“main.js”
に変更します。
次に、以下のように、scripts
セクションにstart
スクリプトを追加してください。
ファイルを保存して閉じます。この時点で、以下のコマンドで新しいElectron.jsアプリケーションを実行できます。
これにより、アプリケーションが起動し、ホーム画面がロードされます。
シンプルなタスクリストシステムを作る
Electrion.jsの他の機能を学ぶために、シンプルなタスクリストシステムを作成します。
まず始めに、アプリケーションのホーム画面に基本的なコンテンツを追加します。
index.htmlファイルを開き、以下のようにBootstrapライブラリをhead
セクションのmeta
タグの下に追加してください。
次に、body
要素内のh1
タグの下に、2カラムのレイアウトを作成するために、以下のハイライトされた行を追加します。1カラム目にはタスクリストが入ります。
現在アプリケーションが起動している場合は、コマンドプロンプトのCtrl+Cキーを押してアプリを終了させた後、npm start
を実行してアプリを再起動させます。以下の画面が表示されます。
Electron.jsのAPIを利用したデスクトップ通知の表示
このセクションでは、タスクリストに新しい項目を追加し、項目が追加されたときに通知を表示する機能を実装します。このセクションの目的は、レンダラープロセスとメインプロセスの間の通信をデモンストレーションすることです。
タスクリストへの新規項目の追加
index.htmlファイルに、form inputとbutton要素を追加します。ユーザーはこれらの要素を操作して、タスクリストに新しい項目を追加します。これらの要素を追加するには、以下のハイライトされた行をコピーして、2カラムグリッドの2つ目のカラムに貼り付けます。
ここで、プロジェクトのルートにscript.jsという新しいJavaScriptファイルを作成し、以下のようにindex.htmlファイルにインポートしてください。
script.jsファイルに、以下のコードを追加します。
上記のコードでは、index.htmlで追加したbutton
要素にclick
イベントハンドラーを追加しています。ボタンがクリックされると、入力フィールドの値が新規の <li>
要素に挿入され、タスクリストに追加されます。
ここで、アプリケーションを終了し、再起動します。入力フィールドに値を入力し、Add Taskボタンをクリックして、いくつか新しい項目を追加してみてください。
新着アイテムのお知らせを表示する
アプリケーションに追加する最後の機能は、デスクトップ通知です。リストに新しい項目が追加されるたびに、通知が表示されます。Electron.jsはレンダラープロセスからHTML 5 Notifications APIを使って通知を作成できるにもかかわらず、メインプロセスでのみ利用できるElectron.js Notificationモジュールを使用することになります。したがって、レンダラープロセスは、通知を機能させるために、メインプロセスと通信する必要があります。
これを実現するために、今回はipcRenderer
とipcMain
モジュールを使用します。ここでは、メインプロセスにshow-notification
イベントを送信し、ペイロードとして task
を送信するためにipcRenderer
モジュールを使用します。script.jsを以下のように変更してください。
レンダラープロセスの中でrequire
にアクセスできるのは、main.jsで nodeIntegration: true
を設定しているからです。これにより、Node.jsのAPIにアクセスできます。
Mainプロセスはこのイベントに対応し、新しいタスクの通知を表示する必要があります。
まず、main.jsの1行目を以下のように変更します。
これは、Electron.jsパッケージからipcMain
とNotification
モジュールのインポートを追加するものです。次に、main.jsにある既存のコードの下に、以下を追加します。
上記のコードでは、レンダラープロセスから送信されるshow-notification
イベントをリッスンし、通知を作成して表示するために、ipcMain
を使用しています。
アプリケーションをテストする
これまでに書いたコードをテストするために、アプリケーションを終了し、再起動します。アプリケーションが正常にロードされたら、新しいタスクを追加してください。画面右上に以下のような通知ポップアップが表示されます。
macOS(および他の一部のオペレーティングシステム)では、アプリケーションからの通知を表示するための許可を承認するよう求めるプロンプトが表示される場合があります。通知を表示するためには、この要求を承認してください。
最後に
Electron.jsは、Web開発者が既存のスキルを活かしてネイティブアプリケーション開発に参入するための大きな力となり、アプリケーション開発の世界に大きな変化をもたらしました。
本稿では、以下をご紹介しました。
- Electron.jsとは何か、Electron.jsを使うべき理由
- Electron.jsのプロジェクトの構造と動作について
- Electron.jsプロジェクトをビルドするための前提条件とビルド方法
- Electron.jsのプロジェクトでネイティブプラットフォームの機能を利用する方法
次のステップ
さらに、このアプリケーションを拡張するために、以下のいずれかの方法をとることができます。
- アプリを認証して利用するための認証機能の追加(Twilio Verifyをご確認ください。)
- デスクトップアプリに音声機能を追加する(Twilio Programmable Voiceをご確認ください。)
Fikayo Adepojuは、10年以上の経験を持つフルスタックのWebおよびモバイル開発者です。現在、フルタイムのテクニカルコンテンツクリエイターとして、さまざまなブログに技術記事を書いたり、ビデオコースを作ったりしていpます。現在は開発者と知識を共有することに注力しています。ご連絡はTwitterのDMからどうぞ! @coderonfleek