React+ElectronでHello Worldする


アプリケーションの作成

通常のReactアプリと同じように、create-react-appコマンドで作成します。

create-react-app helloworld

helloworldはアプリ名です。好きに付けてください。この名前がアプリケーションのディレクトリ名になります。以後の操作はこのディレクトリ内で行うので、このディレクトリに移動してください。

cd helloworld

必要なライブラリーのインストール

次にElectronアプリ開発に必要なライブラリーをインストールします。

npm install electron electron-packager concurrently --save-dev
  • electron は開発時に実行ファイルをビルドすることなくアプリケーションを実行するためのモジュールです。
  • electron-packager はスタンドアロン実行可能な実行ファイルを作成するためのモジュールです。
  • concurrently は複数のコマンドを並行実行するためのモジュールです。

ビルドスクリプトの編集

package.json内のscriptsブロックを以下のように編集します。デフォルトのstart,buildスクリプトをreact-start,react-buildに変更した上で、Electron用のスクリプトを追加しています。

package.json
{
  ...
  "scripts": {
    // Electron のビルドスクリプト
    "electron-dev": "set ELECTRON_START_URL=http://localhost:3000 && electron public",
    "electron-build": "electron-packager build --platform=all --overwrite --asar",

    // React のビルドスクリプト
    "react-start": "react-scripts start", // 元の "start" から変更
    "react-build": "react-scripts build", // 元の "build" から変更

    // 開発時に使用
    "start": "concurrently \"npm run react-start\" \"npm run electron-dev\"",

    // ビルド時に使用
    "build": "npm run react-build && npm run electron-build"
  },
  // Reactのビルド時にリソースを相対パスで読み込むようにする
  "homepage": "./",
  "devDependencies": {
    ...
  }
}

electron-devは環境変数ELECTRON_START_URLを設定した上でelectron publicを実行します。electron-buildはElectronのスタンドアロン実行ファイルを作るコマンドです。詳しくはelectron-packagerの使い方を調べてください。

"homepage": "./"を指定することでReactのビルド時にソースの読み込み先が相対パスになります。これを付けておかないと最終的にビルドされたElectronアプリでのリソース読み込みがうまくいかなくなってしまいます。

Electron実行用のファイルを追加

publicディレクトリ内に以下の二つのファイルを追加します。

public/package.json
{
  "name": "helloworld",
  "version": "1.0.0",
  "main": "main.js"
}
public/main.js
const { app, BrowserWindow } = require('electron')
const path = require('path')
const url = require('url')

let mainWindow

function createWindow() {
  mainWindow = new BrowserWindow({ width: 800, height: 600 })

  // 環境変数 ELECTRON_START_URL が定義されていればそれを使う。なければ index.html を使う。
  const startUrl = process.env.ELECTRON_START_URL || url.format({
    pathname: path.join(__dirname, 'index.html'),
    protocol: 'file:',
    slashes: true
  })
  mainWindow.loadURL(startUrl)

  // 開発中のみ開発者ツールを表示
  if (process.env.ELECTRON_START_URL) {
    mainWindow.webContents.openDevTools()
  }

  mainWindow.on('closed', _ => {
    mainWindow = null
  })
}

app.on('ready', createWindow)

app.on('window-all-closed', _ => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', _ => {
  if (mainWindow === null) {
    createWindow()
  }
})

main.jsはelectron-quick-startのmain.jsをちょっといじったものですが、BrowserWindowに読み込むURLを設定する箇所で環境変数ELECTRON_START_URLを見て、開発時とビルド時で読み込むURLを分けるようにしています。それ以外は通常のmain.jsと変わりません。

実行

ここまでできたら、Electronでアプリを実行してみましょう。

npm start

ローカルサーバーが立ち上がり、ブラウザでページを開くと同時にElectronが起動して同じページを表示します。この状態でsrc/App.jsなどを編集すると、自動的に再コンパイルが走って変更が反映されます。

ビルド

コードが書けたら配布するためのファイルを作ります。

npm build

プロジェクトのディレクトリ以下にhelloworld-win32-x64などができます。これを配布すれば開発環境のない別のマシンでも実行できます。