外部URLやWebサービスを Electron でデスクトップアプリにするのをやってみる(2022年2月版)

2022/02/19に公開

Google を Electron アプリ化してみます。
用途は特にないですが、Google の URL で実現できれば
外部URLやWebサービスを Electron アプリにするのは手順としては同じです。

TL;DR

Electron アプリをクイックスタート+αでやる

まずはクイックスタートどおり進める

基本はクイックスタートと変わらないのでクイックスタートどおりでやっていきましょう。
今回は yarn で進めていきます。

まずは何はともあれ yarn init

$ mkdir my-electron-app && cd my-electron-app
$ yarn init

で、さっそくクイックスタートを無視しますが
アプリのエントリポイントは yarn init のデフォルトである index.js にします。
(なんで main.js にしてるんだろ?)

なので package.json はこんな感じですね

package.json
{
  "name": "my-electron-app",
  "version": "0.0.1",
  "main": "index.js",
  "author": "your name",
  "license": "MIT"
}

そしたら electron パッケージも導入しておきましょう。

$ yarn add --dev electron

導入したら、 package.json の設定の scripts として
electron . を追加して yarn run (run は省略可) で開発環境を立ち上げられるようにしましょう。

なので package.json はこんな感じですね

package.json
{
  "name": "my-electron-app",
  "version": "0.0.1",
  "main": "index.js",
  "author": "your name",
  "license": "MIT",
  "scripts": {
    "start": "electron ."
  },
  "devDependencies": {
    "electron": ">=17.0.1"
  }
}

さて、ここから先は Electron のクイックスタートと違う感じで進めていきます。
Electron のクイックスタートは Electron に描画する画面を
index.html として用意して進めていきますが、
今回は外部URLやWebサービスを Electron アプリにするので
Electron プロジェクトの中に HTML ファイルは用意しません。

すでに Web 上に公開されているURLを使います。
今回は Google を開くアプリを作りましょう。

本来、クイックチュートリアルで作るファイル

  • main.js
    • アプリのエントリポイントです
    • ここから index.html を呼び出して描画します
  • index.html
    • アプリの画面を構成するための HTML ファイルです
  • preload.js
    • 最初これが何か全然ピンとこなかった
    • クイックスタートでは index.html でJavaScriptコードを動かすための JavaScript ファイルです
    • クイックスタート程度の処理だと、 <script> タグを使って index.html に書いちゃってもいいと思うんですが、例なのでわざわざ外部ファイルにしてるだけみたいですね

今回の記事で作るファイル

  • index.js
    • 上述しましたが今回は index.js をエントリポイントにしています
    • これだけです

作っていく

my-electron-app ディレクトリ直下に index.js を作成して処理を記述していきます。
※下記では toutch コマンドでファイル生成してますが方法はなんでもいいです。

$ toutch index.js

中身はこんな感じ。ほとんど Electron クイックチュートリアルの main.js と変わりません。
クイックスタートの main.js と違うポイント をコメントしてあります。

index.js
// アプリケーションの寿命の制御と、ネイティブなブラウザウインドウを作成するモジュール
const { app, BrowserWindow } = require('electron')

const rootUrl = 'https://www.google.com/' /* 違うポイントその1 */

const createWindow = () => {
  // ブラウザウインドウを作成します。
  const mainWindow = new BrowserWindow({
    width: 1024,
    height: 640,
  })

  mainWindow.loadURL(rootUrl) /* 違うポイントその2 */

  // デベロッパー ツールを開きます。
  // mainWindow.webContents.openDevTools()
}

// このメソッドは、Electron の初期化が完了し、
// ブラウザウインドウの作成準備ができたときに呼ばれます。
// 一部のAPIはこのイベントが発生した後にのみ利用できます。
app.whenReady().then(() => {
  createWindow()

  app.on('activate', () => {
    // macOS では、Dock アイコンのクリック時に他に開いているウインドウがない
    // 場合、アプリのウインドウを再作成するのが一般的です。
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

// macOS を除き、全ウインドウが閉じられたときに終了します。 ユーザーが
// Cmd + Q で明示的に終了するまで、アプリケーションとそのメニューバーを
// アクティブにするのが一般的です。
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit()
})
  • クイックスタートの main.js と違うポイント
    • 違うポイントその1
      • アクセスする先のURLを定数にしてるだけです
    • 違うポイントその2
      • クイックスタートでは mainWindow.loadFile('index.html') で index.html を読み込みますが、今回の記事では mainWindow.loadURL(rootUrl) でURLを読み込みます
      • 実質、違うのはここだけです

では動かしてみましょう。

$ yarn start

できました。簡単ですね!
const rootUrl = 'https://www.google.com/' の部分のURLを変えれば
どんなサイトやWebサービスも Electron アプリにできます。
この作業だけだと右クリックメニューが何もないとか、色々不便もあるのですが
簡単なのはいいことです。
自分で作ったWebアプリなんかも Vercel とかにデプロイして今回の手順を実施すれば
簡単にデスクトップアプリにできます。

パッケージングする

配布できる形にもしましょう。
Electron のクイックスタートでは electron-forge を使っていますが
今回は electron-builder を使います。
好きなの使えばいいと思いますが、
Googleトレンドを見る感じ electron-builder の検索量が多いですし
使ってみても使いやすかったです。

https://www.electron.build/

Quick Setup Guide にある感じで進めていきます。
まずはパッケージを追加しましょう。

$ yarn add --dev electron-builder

そしたら package.json にパッケージングに必要な情報と
ビルドコマンドを yarn run できる設定を入れていきます。

全部やるとこんな感じですね。

package.json
{
  "name": "my-electron-app",
  "version": "0.0.1",
  "main": "index.js",
  "author": "your name",
  "license": "MIT",
  "scripts": {
    "start": "electron .",
    "build_mac": "electron-builder --mac --x64",
    "build_win": "electron-builder --win --x64"
  },
  "devDependencies": {
    "electron": ">=17.0.1",
    "electron-builder": ">=22.14.5"
  },
  "build": {
    "appId": "<your app id>",
    "productName": "electron_app",
    "directories": {
      "output": "build"
    },
    "files": [
      "index.js",
      "package.json",
      "yarn.lock"
    ],
    "mac": {
      "icon": "resources/ovice_icon.icns",
      "target": [
        "dmg"
      ]
    },
    "win": {
      "icon": "resources/ovice_icon.ico",
      "target": "nsis"
    },
    "nsis": {
      "oneClick": false,
      "allowToChangeInstallationDirectory": true
    }
  }
}

ざっくり解説していくと

  • "build": {
    • この配下に electron-builder の設定を書いています
  • "appId":
    • アプリを一意に区別するためのIDです。私は自分のWebサイトのドメインを逆にしたもの+アプリ名とかにすることが多いです。
  • "productName":
    • アプリの名前です。指定しない時はトップレベルの "name": が使われます
  • "directories":
    • 出力先を指定しています
  • "files": [
    • アプリに含めるファイルを指定しています。今回は3つだけなので単純に列挙してますが、ワイルドカードなどでまとめて指定することもできます
  • "mac": {
    • macOS 版の設定です。今回はアイコンと拡張子を指定しています。アイコンについては後述
  • "win": {
    • Windows 版の設定です。今回はアイコンと拡張子を指定しています。アイコンについては後述
  • "nsis": {
    • Windows 版の NSIS (Nullsoft Scriptable Install System) 用の設定です

アイコンについて

macOS、Windows のアプリにするにあたってアイコンを用意します。
今回は sprout2000/elephicon を使ってアイコンを生成して
my-electron-app/resources/ 配下に配置しました。
pngファイルを突っ込んでやるだけでアイコンファイルをよしなに生成してくれるので便利でした。

https://github.com/sprout2000/elephicon

package.json とアイコンの準備ができたらビルドする

yarn run スクリプトの設定も済ませてあるのでビルドしましょう。
私は M1 Macbook Air を使っているのですが、
arm 出力だとなぜか同じ M1 Macbook Air の人に渡してもインストールできなったので
electron-builder --mac --x64 で出力しています。

$ yarn build_mac

コマンドを実行すると、 build/ 配下に dmg ファイルが出力されているはずです。
後はこのファイルを自分なり他の人に渡せばインストールして使ってもらうことができます。

デスクトップアプリとして正式に公開するためには署名情報を入れないといけないのですが
今回はそこまでやりません。
そのため、例えば macOS であればインストール後初回起動時に
Ctrlキー+右クリックから「開く」して「署名されてないアプリですが起動しますか?」「はい」
とかやります。

以上

以上です。おつかれさまでした!
今回作ったプロジェクトは以下に置いてあります。

https://github.com/JUNKI555/electron_practice03

なんで npm じゃなくて yarn 使ってるんですか?

yarn が好きだからです

npm がデフォルトなんだから npm の方がラクでは?

node.js のバージョン管理のために nodenv とかを使う方も多いと思います。
最近 Volta というバージョン管理ソフトウェアがいい感じで
こいつを使えば yarn も一緒にバージョン管理できるのでデフォルトかどうかはあんまり気にしなくて良くなったと思います。

https://volta.sh/

詳しくはこちらなど参照してください

その他参考にしたサイト

Discussion