🐥

Electronのチュートリアルをやってみた

2021/11/18に公開

自分用のデスクトップアプリを作ろうと色々調べてみたところ、Electronというものがあることを知りました。普段はWEB制作関係の仕事が多いので、HTML, CSS, JSという自分の理解できるものを用いてアプリが作れることに惹かれ、とにかく使い勝手を知るためにチュートリアルを進めてみました。

流れ

  1. ディレクトリ作成
mkdir my-electron-app && cd my-electron-app
  1. pacage.jsonの作成
npm init
  1. electronのインストール
npm install --save-dev electron
  1. コマンド追加
package.json
{
  "scripts": {
    "start": "electron ."
  }
}
  1. 実行

ここで起動を行ってもアプリが立ち上がるだけで、それ以外にには何も起きない。

npm start
  • npm initで指定したエントリーポイント(main)のファイルがないとエラーになる。
    このファイルが、アプリのすべての動作の元になる。
  1. 表示されるコンテンツの作成(index.html)

  2. 6のコンテンツを表示するため、2つのモジュールを準備

main.js
const { app, BrowserWindow } = require('electron')

// index.htmlを読み込み、新しいウィンドウで表示する
const createWindow = () => {
    const win = new BrowserWindow({
        width: 800,
        height: 600
    })

    win.loadFile('index.html')
}

// electronでは、ブラウザウィンドウは、readyイベントの後にしか作成できない
app.whenReady().then(() => {
  createWindow()
})

上記の状態までできれば、npm startでアプリを動かせる(index.htmlの表示しかできないが)

app module controls event lifecycle
BrowserWindow module create and manages app windows

  • require is CJS(CommonJS Modules)の読み込み仕様 => NodeJSで動く
    import is ESM(ECMAScript Modules)の読み込み仕様 => 最近のブラウザで動く
    => webpackなどのモジュールバンドラーで,どの環境でも動くようにできる

より詳しくは、 https://qiita.com/minato-naka/items/39ecc285d1e37226a283

  1. (特定のOSでのみ処理を追加したい場合)

processのplatform属性を利用すれば、可能

main.js
// darwin(mac)でなければ、ウィンドウがすべて閉じられたら、アプリを終了する
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit()
})

macでは、ウィンドウを閉じてもアプリが動作しているのが一般的
ウィンドウが使用できないときにアプリをアクティブにすると、新しいアプリを開くようにするには以下のようにする。

main.js
app.whenReady().then(() => {
  createWindow()

  // 追加 
  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

  1. version情報を表示する

プロセスが異なるため、mainプロセスからレンダリングされたDOMにアクセスできない!!
=> preloadを用いて、どちらにもアクセスできる

preload.js
window.addEventListener('DOMContentLoaded', () => {
  const replaceText = (selector, text) => {
    const element = document.getElementById(selector)
    if (element) element.innerText = text
  }

  for (const dependency of ['chrome', 'node', 'electron']) {
    replaceText(`${dependency}-version`, process.versions[dependency])
  }
})
main.js
const { app, BrowserWindow } = require('electron')
const path = require('path')

const createWindow = () => {
    const win = new BrowserWindow({
        width: 800,
        height: 600,
        webPreferences: { // preloadを用いることでNodeの変数も、DOMなども扱える
            preload: path.join(__dirname, 'preload.js')
        }
    })

    win.loadFile('index.html')
}

app.whenReady().then(() => {
    createWindow()

    // アクティベート時に、ウィンドウが1つもなければ、ウィンドウを作成する 
    app.on('activate', () => {
        if (BrowserWindow.getAllWindows().length === 0) createWindow()
    })

    // mac以外のOSでは、すべてのウィンドウが閉じられたら、アプリを終了する
    app.on('window-all-closed', () => {
        if (process.platform !== 'darwin') app.quit()
    })
})

ちなみに、もちろんHTMLでjsを呼び出せる(node jsの情報は取得できない)

  1. パッケージ化する

electron Forgeというものがあるらしい。
簡単にパッケージ化できる様子(他にも色々できるらしい)

Forgeをインストール

npm install --save-dev @electron-forge/cli
npx electron-forge import

Forge のmakeコマンドを利用して配布できる状態にする

npm run make
  1. +α dev toolsを表示してみる

理由はわかっていませんが、チュートリアル通りにすすめても、dev toolsが表示されませんでした。
なのでpackage化されていなければ、devtoolsを開く設定を追加してみました。

main.js
const createWindow = () => {
    const win = new BrowserWindow({
        width: 800,
        height: 600,
        webPreferences: {
            preload: path.join(__dirname, 'preload.js')
        }
    })

    if (!app.isPackaged) {
        win.webContents.openDevTools();
    }

    win.loadFile('index.html')
}

所感

基本的なことしか行っていませんが、そこまで難しくなさそうです。Electronの基本的な機能、よくある処理の書き方、ライフサイクルがどのようなものなのかが、おおよそわかれば気軽にデスクトップアプリが作れそうです。

Discussion