概要
electron は HTML と JavaScript でデスクトップアプリケーションを作成することができるフレームワークです
今回は簡単な使い方とサンプルを紹介します
また基本となるメインプロセスとレンダラープロセス間で通信するための IPC にも触れます
環境
- macOS 10.14.2
- node 10.1.0
- electron 4.0.3
electron インストール
vim package.json
{
"name": "try_electron",
"version": "1.0.0",
"description": "",
"main": "main.js",
"scripts": {
"start": "electron ."
},
"author": "",
"license": "ISC",
"devDependencies": {
"electron": "^4.0.3"
}
}
npm install --save
Hello World
main.js でウィンドウの表示やイベントの登録を行います
main.js の処理はメインプロセスと呼ばれる処理で外部のサイトへの通信などバックエンドで行う重たい処理などを行います
vim main.js
const { app, BrowserWindow } = require('electron')
let win
function createWindow () {
win = new BrowserWindow({ width: 800, height: 600 })
win.loadFile('index.html')
win.webContents.openDevTools()
win.on('closed', () => {
win = null
})
}
app.on('ready', createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (win == null) {
createWindow()
}
})
vim index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</body>
</html>
実行してみましょう
以下のようにアプリが立ち上がれば OK です
- npm start
トラブルシューティング
Cannot read property 'on' of undefined
というエラーが出ることがありました
自分の場合原因は package.json の start コマンドを node コマンドで実行していたことが原因でした
"scripts": {
"start": "node ."
}
↓
"scripts": {
"start": "electron ."
}
ボタンを作って見る
main.js はそのままです
HTML 上にボタンを配置して別の JS で DOM 操作するだけです
vim index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Button Event</title>
</head>
<body>
<h1>Button Event</h1>
<input type="text" id="input1" size="30">
<button type="button" id="button1">submit</button>
<script type="text/javascript" src="lib.js"></script>
</body>
</html>
新たに lib.js が登場しました
これがレンダラープロセス側で実行される JavaScript になります
普通に Web アプリを作るように主に DOM の操作を行います
vim lib.js
let button = document.getElementById('button1')
button.onclick = function() {
let input = document.getElementById('input1')
console.log(input.value)
}
実行すると以下のように動作します
IPC 通信
electron はメインプロセス (main.js) とレンダラープロセス (lib.js) に分かれています
それぞれでデータのやり取りを行うには IPC というモジュールを使います
main.js は ipcMain
を使うように修正します
またレンダラープロセスから送られた来たイベントをハンドリングするハンドラ (ipc.on
) を追加します
- vim main.js
const { app, BrowserWindow } = require('electron')
const ipc = require('electron').ipcMain
let win
function createWindow () {
win = new BrowserWindow({ width: 800, height: 600 })
win.loadFile('index.html')
win.webContents.openDevTools()
win.on('closed', () => {
win = null
})
}
app.on('ready', createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (win == null) {
createWindow()
}
})
ipc.on('test', function (event, _) {
event.sender.send('test-reply', 'pong')
})
レンダラー側は ipcRenderer
を使ってメイン側にリクエストするイメージです
コールバック関数で結果を受け取ったら DOM 操作なりをすれば OK です
vim lib.js
const ipc = require('electron').ipcRenderer
ipc.send('test', 'ping')
ipc.on('test-reply', function (event, arg) {
document.getElementById("ret").innerHTML = arg
})
- vim index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>IPC Test</title>
</head>
<body>
<h1>IPC Test</h1>
<h2 id="ret"></h2>
<script type="text/javascript" src="lib.js"></script>
</body>
</html>
結果は以下のような感じになります
外部のサイトにアクセスする
IPC を使ってメインプロセス側で行います
また electron には ClientRequest というクラスがありこれを使って外部のサイトにアクセスすることができます
main.js では IPC のハンドリング後外部サイトにアクセスするようにします
またそのレスポンスをレンダラー側に返却する処理も実装します
- vim main.js
const { app, BrowserWindow } = require('electron')
const ipc = require('electron').ipcMain
const net = require('electron').net
let win
function createWindow () {
win = new BrowserWindow({ width: 800, height: 600 })
win.loadFile('index.html')
win.webContents.openDevTools()
win.on('closed', () => {
win = null
})
}
app.on('ready', createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (win == null) {
createWindow()
}
})
ipc.on('check', function (event, arg) {
const request = net.request({
method: 'GET',
protocol: 'https:',
hostname: arg,
port: 443,
path: '/'
})
request.on('response', (response) => {
event.sender.send('check-reply', response.statusCode)
response.on('error', (error) => {
console.log(`ERROR: ${JSON.stringify(error)}`)
})
})
request.end()
})
net.request でリクエストを生成 request に対してレスポンスをハンドリングするためのイベントハンドラを登録、そして request.end()
で実際にリクエストをコールします
結果をハンドラで受け取ったら IPC を使って結果をレンダラーに渡します
レンダラー側はボタンを押したら github.com のステータスを取得してもらうようにメイン側に依頼します
- vim lib.js
let button = document.getElementById('button1').onclick = function() {
const ipc = require('electron').ipcRenderer
ipc.send('check', 'github.com')
ipc.on('check-reply', function (event, arg) {
document.getElementById("ret").innerHTML = arg
})
}
- vim index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Github Status</title>
</head>
<body>
<h1>Github Status</h1>
<button type="button" id="button1">check</button>
<h2 id="ret"></h2>
<script type="text/javascript" src="lib.js"></script>
</body>
</html>
これで実行しボタンをクリックすると github.com にアクセスしレスポンスコードを表示してくれます
パッケージング
もし各プラットフォームで配布する場合には指定のフォーマットにパッケージングする必要があります
便利な electron-packager というツールがあるのでそれを使いましょう
npm install electron-packager --save-dev
インストールはこれで完了です
package.json の package というコマンドを追加しましょう
vim package.json
{
"name": "try_electron",
"version": "1.0.0",
"description": "",
"main": "main.js",
"scripts": {
"start": "electron .",
"package": "electron-packager . test --platform=darwin --arch=x64 --app-version=1.0.0"
},
"author": "",
"license": "ISC",
"devDependencies": {
"electron": "^4.0.3",
"electron-packager": "^13.0.1"
}
}
あとは実行するだけです
npm run package
完了すると xxxx-darwin-x64
というディレクトリが作成されます
今回であれば test-darwin-x64 です
xxxx.app
というファイルが直下にあるのでそれを Applications 配下に配置すればインストール完了です
また Windows 用にパッケージングしたい場合は platform
オプションに win32
を追加します
最後に
electron に入門してみました
最低限の electron のアーキテクチャや API を覚える必要はありますが、ほぼ UI などはほぼ Web を開発する方法と同じ感覚で開発できるのは嬉しい点かなと思います
HTML/JavaScript なので何も考えずマルチプラットフォームで開発できるのも嬉しい点かなと思います
0 件のコメント:
コメントを投稿