4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Electronアプリを作成した時に学んだこと

Last updated at Posted at 2020-08-14

最近の業務中にデスクトップアプリが欲しいという要望がありましたので、初めてElcetronを使ってアプリを作成してみた時に学んだことをメモしました。

環境

  • OS: MacOS Catalina v10.15.5
  • Node.js: v12.16.3
  • NPM: v6.14.4
  • Electron: v9.1.0
  • electron-builder: 22.7.0

Node.js & NPM

Node.jsのインストールについて、こちらを参考してください。
https://nodejs.org/ja/

NPMはNode.jsの中に同梱されていますので、Node.jsをインストールすればNPMもインストールされます。

Electron

Build cross-platform desktop apps with JavaScript, HTML, and CSS

公式サイトには、このような説明を書いています。
開発会社はGithub社でもあり、これを使って作った有名なソフトウェアも沢山あります。
(VS Code, Slack, VS Code, Slack, Microsoft teams...etc)

インストール方法は、プロジェクトの配下に下記のコマンドを実行する。

npm install --save-dev electron

Main Process & Renderer Processの概要

Main process
package.jsonmainに設定しているscriptはElectronのMain processになります。
ElectonアプリにMain processは一つだけでして、アプリの画面作成、起動、終了の制御はできます。

Main processにBrowserWindowで画面を作成し、画面を描画するprocessはrenderer processと呼ばれます。
一つの画面は一つのrenderer processで制御されます。

Main processでは、Node.jsのAPIを利用できますので、OS機能レベルのやりとりは可能です。

Renderer Process
Main processには、BrowserWindowインスタンスでRenderer processを作成し、Chromiumで画面を描画します。
複数Renderer processは可能です。各Renderer processは独立しています。
基本的には、ネイティブGUIのAPIを操作することを禁止されますので、必要があればMain process経由((IPC通信))で行う方法はあります。
なので、Renderer processにはブラウザで使えるJavaScriptを動きます。

main.js (Main process)

アプリのMain processになります。

アプリの制御と画面を作成にはElectron APIを使用するため、electronをrequireします。

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

画面作成

const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
        nodeIntegration: false,
        contextIsolation: false,
        preload: __dirname + "/preload.js"
    }
})

win.openDevTools();
win.loadFile(__dirname + "/index.html")

BrowserWindowインスタンスを作成し、画面のサイズを設定できます。
nodeIntegration, contextIsolation, preloadの設定は、Renderer processでNPMのモジュール、Node.js APIを使えるため、直接にAPIを使うことではなく、preload.js経由で使うようにすることです。

ここのnodeIntegrationfalseにしています。trueにしてしまうとRenderer processでは普通にNode.js APIを使えるようになりますが、かなりの操作権限をRenderer processに与えていますので、想定外の挙動やセキュリティー周りの影響も発生しやすいです。例えば、ElectronアプリでPC内のファイルを全部削除することも可能です。ようこそ!Electron入門

loadFile関数で表示する画面の指定ができます。
また、openDevTools関数でChromeのデベロッパー ツールをデフォルトで表示します。

アプリのイベント検知
参考:app

app.whenReady().then(...)
app.on('window-all-closed', () => {})
app.on('activate', () => {})
...

よく使うのはreadywindow-all-closedactivateです。
イベントが発火する際に特定処理を行うことはできます。

main.jsの例:

main.js
const { app, BrowserWindow } = require('electron')
const path = require("path")
function createWindow () {
  // Create the browser window.
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: false,
      preload: path.join(__dirname + "/preload.js")
    }
  })

  // and load the index.html of the app.
  win.loadFile(path.join(__dirname + "/index.html"))
}

app.whenReady().then(createWindow)

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

app.on('activate', () => {
    // On macOS it's common to re-create a window in the app when the
    // dock icon is clicked and there are no other windows open.
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow()
    }
})

index.html (Renderer process)

こちらのindex.htmlmain.jsには、BrowserWindowloadFile関数に指定されてるHTMLファイルです。

普通のウェブページを作成する方法と同じくHTML、CSS、Javascriptの記述はできます。

index.htmlの例

index.html
<!DOCTYPE html>
<html>
  <head>
  </head>
  <body>
    <h2 id=counter value=0>0</h2>
    <button onclick="counter()">Add</button>
  </body>
  <script>
    function counter() {
    var counter = document.getElementById('counter')
    var count = parseInt(counter.textContent)
    count++
    counter.textContent = count
  }
  </script>
  <style>
  
  </style>
</html>

preload.js

Renderer processで使うNode.js、npmnのモジュール、Electron APIを提供する。

例えば、下記のように記述したら、electron, fsの変数をRenderer processに渡すようになります。

preload.js
const electron = require('electron');
const fs = require('fs')

process.once('loaded', () => {
    global.electron = electron
    global.fs = fs
});

index.htmlでは、下記のように記述すればelectron, fsのAPIを使えるようになります。

index.html
const electron = window.electron;
const csvFileUtil = window.csvFileUtil

ビルド

こちらではelectron-builderを使って、Mac PCとWindows PCも実行できるアプリをビルドしました。

electron-builderのインストール

npm install -D electron-builder

package.jsonの編集

package.jsonにビルドの設定を追加します。

{
  "name": "app name",
  "version": "1.0.0",
  "description": "electron application",
  "main": "src/main.js",
  "build": {
    "appId": "com.example.my-app",
    "directories": {
      "output": "dist"
    },
    "files": [
      "assets",
      "src",
      "package.json",
      "package-lock.json"
    ],
    "mac": {
      "icon": "assets/icon/app_icon.png",
      "target": [
        "dmg"
      ]
    },
    "win": {
      "icon": "assets/icon/app_icon.png",
      "target": "nsis"
    },
    "nsis": {
      "oneClick": false,
      "allowToChangeInstallationDirectory": true
    }
  },
  "devDependencies": {
    "electron-builder": "^22.7.0",
    "electron": "^9.1.0"
  },
  "scripts": {
    "start": "electron --inspect=5858 .",
    "build-win": "node_modules/.bin/electron-builder --win --x64",
    "build-mac": "node_modules/.bin/electron-builder --mac --x64",
    "pack": "electron-builder --dir",
    "dist": "electron-builder",
    "postinstall": "electron-builder install-app-deps"
  }
}

buildの部分はビルトの設定になります。

今回アプリのプロジェクトの構成はこのようになっています。

myapp
 -- assets
    -- css
       -- style.css
    -- icon
       -- app_icon.png
 -- node_modules
 -- src
    -- main.js
    -- index.html
    -- preload.js
 -- package.json

ソースコードは一つフォルダー(src)の配下に入れています。
(よくわからないですが、最初にpreload.jsをmyapp配下に別のフォルダに保存していましたが、ビルドしてみたら、preload.jsが一緒にビルドされないことが発生しましたので、srcに入れたらうまくビルドされるようになりました。)
参考:configuration

ビルドの実行について

先ほどのpackage.jsonの例のscriptの部分に記載している通り、scriptを実行するとアプリのビルドが行われます。

Windows用のアプリを作成したい場合、npm run build-winを実行したら、distの配下にwin-unpackedフォルダとインストール用の.exeファイルが作成されます。
win-unpackedフォルダの中にWindows環境で実行できるファイルがあります。

Mac PC用のアプリを作成したい場合、npm run build-macを実行したら、distの配下にmacフォルダとインストール用の.dmgファイルが作成されます。
macフォルダの中にMac環境で実行できるファイルがあります。

注意点

ファイルパスの記述には、Macだと/を使いますが、Windowsだと\を使います。このような違いがあると処理する時に気をつける必要があります。Node.jsのpathAPIを使ったらその辺をうまく処理してくれますので、パスの部分をpathAPIで処理しましょう。
参考:path

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?