Electronでストップウォッチを作る
そう言えばJavaScript(Node.js)でデスクトップアプリ作れるよなと思って、以前Reactで作ったストップウォッチをElectronでデスクトップアプリ化してみようと思い立ったのでやってみた。
セットアップ
Electron + Reactでデスクトップアプリを作ろう! - Qiita
この記事を参考に Electron React Boilerplate
を使ってセットアップを行う。
Installation | Electron React Boilerplate
satoshie@MainMachine ~/git> git clone --depth=1 \
https://github.com/electron-react-boilerplate/electron-react-boilerplate \
stop-watch-by-electron
Cloning into 'stop-watch-by-electron'...
remote: Enumerating objects: 93, done.
remote: Counting objects: 100% (93/93), done.
remote: Compressing objects: 100% (86/86), done.
remote: Total 93 (delta 8), reused 54 (delta 3), pack-reused 0
Receiving objects: 100% (93/93), 697.12 KiB | 3.67 MiB/s, done.
Resolving deltas: 100% (8/8), done.
satoshie@MainMachine ~/git> cd stop-watch-by-electron/
satoshie@MainMachine ~/g/stop-watch-by-electron (main)> npm i
npm WARN deprecated stable@0.1.8: Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility
npm WARN deprecated asar@3.2.0: Please use @electron/asar moving forward. There is no API change, just a package name change
npm WARN deprecated electron-osx-sign@0.6.0: Please use @electron/osx-sign moving forward. Be aware the API is slightly different
npm WARN deprecated @types/terser-webpack-plugin@5.2.0: This is a stub types definition. terser-webpack-plugin provides its own type definitions, so you do not need this installed.
npm WARN deprecated @npmcli/move-file@2.0.1: This functionality has been moved to @npmcli/fs
> postinstall
> ts-node .erb/scripts/check-native-dep.js && electron-builder install-app-deps && cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.renderer.dev.dll.ts
• electron-builder version=23.6.0
• loaded configuration file=package.json ("build" field)
• installing production dependencies platform=darwin arch=x64 appDir=/Users/satoshie/git/stop-watch-by-electron/release/app
added 1392 packages, and audited 1393 packages in 57s
208 packages are looking for funding
run `npm fund` for details
6 high severity vulnerabilities
To address all issues (including breaking changes), run:
npm audit fix --force
Run `npm audit` for details.
パッケージの問題は追々対応する。
起動してみる
$ npm start
> start
> ts-node ./.erb/scripts/check-port-in-use.js && npm run start:renderer
> start:renderer
> cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack serve --config ./.erb/configs/webpack.config.renderer.dev.ts
Starting preload.js builder...
Starting Main Process...
<i> [webpack-dev-server] Project is running at:
<i> [webpack-dev-server] Loopback: http://localhost:1212/
<i> [webpack-dev-server] On Your Network (IPv4): http://172.22.5.60:1212/
<i> [webpack-dev-server] On Your Network (IPv6): http://[fe80::1]:1212/
<i> [webpack-dev-server] Content not from webpack is served from '/Users/satoshie/git/stop-watch-by-electron/public' directory
<i> [webpack-dev-server] 404s will fallback to '/index.html'
> start:main
> cross-env NODE_ENV=development electronmon -r ts-node/register/transpile-only .
> start:preload
> cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.preload.dev.ts
[electronmon] waiting for a change to restart it
[90295:0224/030606.617624:ERROR:trust_store_mac.cc(838)] Error parsing certificate:
ERROR: Failed parsing extensions
(node:90295) ExtensionLoadWarning: Warnings loading extension at /Users/satoshie/Library/Application Support/Electron/extensions/fmkadmapgofadopljbjfkapdkoienihi:
Permission 'scripting' is unknown or URL pattern is malformed.
(Use `Electron --trace-warnings ...` to show where the warning was created)
03:06:08.074 › Skip checkForUpdates because application is not packed and dev update config is not forced
03:06:08.079 › checkForUpdatesAndNotify called, downloadPromise is null
(node:90295) ExtensionLoadWarning: Warnings loading extension at /Users/satoshie/Library/Application Support/Electron/extensions/fmkadmapgofadopljbjfkapdkoienihi:
Permission 'scripting' is unknown or URL pattern is malformed.
03:06:08.164 › Skip checkForUpdates because application is not packed and dev update config is not forced
03:06:08.165 › checkForUpdatesAndNotify called, downloadPromise is null
(node:90295) ExtensionLoadWarning: Warnings loading extension at /Users/satoshie/Library/Application Support/Electron/extensions/fmkadmapgofadopljbjfkapdkoienihi:
Permission 'scripting' is unknown or URL pattern is malformed.
03:06:08.235 › Skip checkForUpdates because application is not packed and dev update config is not forced
03:06:08.239 › checkForUpdatesAndNotify called, downloadPromise is null
[90295:0224/030608.773653:ERROR:extensions_browser_client.cc(62)] Extension Error:
OTR: false
Level: 2
Source: chrome-extension://jajkcfjjopeknfifcbmdnjehnepnldgn/build/background.js
Message: Uncaught TypeError: Cannot read properties of undefined (reading 'registerContentScripts')
ID: jajkcfjjopeknfifcbmdnjehnepnldgn
Type: RuntimeError
Context: chrome-extension://jajkcfjjopeknfifcbmdnjehnepnldgn/build/background.js
Stack Trace:
{
Line: 107
Column: 1
URL: chrome-extension://jajkcfjjopeknfifcbmdnjehnepnldgn/build/background.js
Function: (anonymous function)
}
[90295:0224/030609.061827:ERROR:extensions_browser_client.cc(62)] Extension Error:
OTR: false
Level: 2
Source: chrome-extension://jajkcfjjopeknfifcbmdnjehnepnldgn/build/background.js
Message: Uncaught TypeError: Cannot read properties of undefined (reading 'registerContentScripts')
ID: jajkcfjjopeknfifcbmdnjehnepnldgn
Type: RuntimeError
Context: chrome-extension://jajkcfjjopeknfifcbmdnjehnepnldgn/build/background.js
Stack Trace:
{
Line: 107
Column: 1
URL: chrome-extension://jajkcfjjopeknfifcbmdnjehnepnldgn/build/background.js
Function: (anonymous function)
}
[90295:0224/030609.269791:ERROR:extensions_browser_client.cc(62)] Extension Error:
OTR: false
Level: 2
Source: chrome-extension://jajkcfjjopeknfifcbmdnjehnepnldgn/build/background.js
Message: Uncaught TypeError: Cannot read properties of undefined (reading 'registerContentScripts')
ID: jajkcfjjopeknfifcbmdnjehnepnldgn
Type: RuntimeError
Context: chrome-extension://jajkcfjjopeknfifcbmdnjehnepnldgn/build/background.js
Stack Trace:
{
Line: 107
Column: 1
URL: chrome-extension://jajkcfjjopeknfifcbmdnjehnepnldgn/build/background.js
Function: (anonymous function)
}
[90295:0224/030609.270111:ERROR:extensions_browser_client.cc(62)] Extension Error:
OTR: false
Level: 1
Source: manifest.json
Message: Service worker registration failed. Status code: 15
ID: jajkcfjjopeknfifcbmdnjehnepnldgn
Type: ManifestError
IPC test: ping
IPC test: ping
IPC test: ping
[90295:0224/030611.894170:ERROR:CONSOLE(2)] "Electron sandboxed_renderer.bundle.js script failed to run", source: node:electron/js2c/sandbox_bundle (2)
[90295:0224/030611.894231:ERROR:CONSOLE(2)] "TypeError: object null is not iterable (cannot read property Symbol(Symbol.iterator))", source: node:electron/js2c/sandbox_bundle (2)
[90295:0224/030611.945934:ERROR:CONSOLE(2)] "Electron sandboxed_renderer.bundle.js script failed to run", source: node:electron/js2c/sandbox_bundle (2)
[90295:0224/030611.946017:ERROR:CONSOLE(2)] "TypeError: object null is not iterable (cannot read property Symbol(Symbol.iterator))", source: node:electron/js2c/sandbox_bundle (2)
[90295:0224/030611.973589:ERROR:CONSOLE(2)] "Electron sandboxed_renderer.bundle.js script failed to run", source: node:electron/js2c/sandbox_bundle (2)
[90295:0224/030611.973642:ERROR:CONSOLE(2)] "TypeError: object null is not iterable (cannot read property Symbol(Symbol.iterator))", source: node:electron/js2c/sandbox_bundle (2)
すぐには起動しないみたい。しばらくするとアプリとして起動した。
useStopWatchを使えるようにする
Git cloneしただけなので、オリジナルのElectron React Boilerplateをベースに必要なコードを足していく。
electron-react-boilerplate/electron-react-boilerplate: A Foundation for Scalable Cross-Platform Apps
まずは react-timer-hookを使えるようにするために npm install でライブラリをインストールする。
satoshie@MainMachine ~/g/stop-watch-by-electron (main)> npm i react-timer-hook
added 1 package, and audited 1394 packages in 8s
208 packages are looking for funding
run `npm fund` for details
6 high severity vulnerabilities
To address all issues (including breaking changes), run:
npm audit fix --force
Run `npm audit` for details.
デジタル時計なフォントをインストールする
ストップウォッチなのでデジタル時計っぽいフォントを使いたい。
今回はフリーフォントの7セグ・14セグフォント 「DSEG」を利用する。
npmパッケージとして公開されているのでnpmコマンドでインストールが可能。
satoshie@MainMachine ~/g/stop-watch-by-electron (main)> npm i dseg
added 1 package, and audited 1395 packages in 7s
208 packages are looking for funding
run `npm fund` for details
6 high severity vulnerabilities
To address all issues (including breaking changes), run:
npm audit fix --force
Run `npm audit` for details.
CSSでフォントをインポートする
フォントを使えるようにCSSファイル内でインポートを記述する。
@import "dseg/css/dseg.css";
ストップウォッチの実装を追加
以前Reactで作ったStopWatchのコードを移植してくる。
ほぼコピペで出来た。
サイズの調整
main/main.ts内にウィンドウサイズの記述があるので適切なサイズに調整する。
mainWindow = new BrowserWindow({
show: false,
width: 320,
height: 200,
icon: getAssetPath('icon.png'),
webPreferences: {
preload: app.isPackaged
? path.join(__dirname, 'preload.js')
: path.join(__dirname, '../../.erb/dll/preload.js'),
},
});
アプリのタイトルを設定する
package.jsonに記載されている productName
がアプリ名なのでこれを書き換える。
"webpack-merge": "^5.8.0"
},
"build": {
- "productName": "ElectronReact",
+ "productName": "Stop Watch",
アプリのウィンドウタイトルは main/menu.ts
で定義されているのでこちらも変更。
@@ -54,7 +54,7 @@ export default class MenuBuilder {
buildDarwinTemplate(): MenuItemConstructorOptions[] {
const subMenuAbout: DarwinMenuItemConstructorOptions = {
- label: 'Electron',
+ label: 'Stop Watch',
アプリのビルド
npm run package
を実行すると、 ./release/build
ディレクトリに各プラットフォーム向けのアプリケーションが作成される。
今回の作業レポジトリ
Discussion