Electron を試す 5 - Electron v0.35.0 対応
Electron v0.35.0 で互換に影響のある変更が入ったため、その対応についてまとめる。既に v0.35.1 もリリースされているけれど、こちらは大きな変更がないため今回は取り扱わない。
v0.35.0 Release Notes
まずは Electron v0.35.0 の Release Notes を確認。
ざっくり意訳。
共通
- Show warnings for deprecated APIs, can be turned off with
process.noDeprecation.- 非推奨の API に対して警告を表示するようにした
- この警告を無効化する場合は
process.noDeprecationを指定すること
- Add
electronmodule which includes all public APIs.electronモジュールを追加して public な API はそこへ含めるようにした
- The
ipcmodule is deprecated, should useipcRendererin renderer process, andipcMainin main process.ipcモジュールを非推奨にした- かわりに Renderer プロセスでは
ipcRenderer、Main プロセスはipcMainを使用すること
- The
ipcRenderermodule adds aneventobject when emitting events, to match the style ofipcMainmodule.ipcRendererのイベント ハンドラーにeventオブジェクトを追加した- この対応により
ipcMainと設計 ( インターフェース ) が等しくなる
- Remove the
-inBrowserWindow's option names.BrowserWindowのオプション名から-を削除した
clickedevents inTrayare renamed toclick.Trayイベントのclickedをclickに名称変更した
- The
Urlin API names is replaced withURL.- API 名の
Urlという表記をURLに置き換えた
- API 名の
- Add
documents,downloads,music,pictures,videoskeys toapp.getPath.app.getPathのキーにdocuments、downloads、music、pictures、videosを追加
- Fix memory leak of
webContents.beginFrameSubscription.webContents.beginFrameSubscriptionのメモリー リークを修正した
Windows
- Add support for toast notifications on Windows >= 8.
- Windows 8 以降のトースト通知に対応した
OS X
- Add
drag-enter,drag-leave,drag-endanddropevents toTraymodule.Trayモジュールのイベントにdrag-enter、drag-leave、drag-end、dropを追加した
- Fix images not showing in notifications on OS X 10.9.
- OS X 10.9 の通知機能で画像が表示されない問題を修正
対応
各種変更の詳細と対応方法をまとめる。
非推奨 API の警告
非推奨の API の使用が警告されるようになった。例えば BrowserWindow.loadUrl を呼び出すと以下のように警告される。
(electron) loadUrl is deprecated. Use loadURL instead.対象となる API は廃止される可能性が高いので早期に修正すること。警告を抑止するなら Main プロセス冒頭で process.noDeprecation に true を代入すればよい。
process.noDeprecation = true;この対応により警告が抑止されることを確認。しかし警告はアプリを修正するための重要なヒントであり、表示による動作への影響もないため抑止しないほうがよいだろう。
public API の electron モジュール移行
electron モジュールが追加され公開 API はそちらに移行された。もしくはされる。これまで私が使用してきたものだと ipc や shell が対象になっている。
個別の API リファレンスに掲載されているサンプルでは変更後のコードになっているため、ひととおり目を通しておいたほうがよい。electron 移行にともない参照方法も変更されている。require を利用するなら electron 配下から読み込む。
const ipcMain = require( 'electron' ).ipcMain;Modules 形式ならば electron に対して明示的に名前指定すればよい。
import { ipcMain } from 'electron';私は Modules 形式を利用するときの命名を PascalCase にしている。しかし ipcMain などは camelCase となるため一貫性が崩れる。またユニット テストで IPC や Shell API をモック化したくなるかもしれない。そのためこれらは require 形式で読み込み、その参照を従属するインスタンスに伝搬する方式で設計している。
import DialogManager from './DialogManager.js';
import WindowManager from './WindowManager.js';
class Main {
constructor() {
// 共有される標準 API
this._ipc = require( 'electron' ).ipcMain;
this._shell = require( 'electron' ).shell;
// this を渡すことで従属するインスタンスは間接的に API を参照する
this._windowManager = new WindowManager( this );
this._dialogManager = new DialogManager( this );
}
}徹底するなら App や BrowserWindow なども間接参照にするべきだが、とりあえずは electron 配下のものだけにしている。
ipc モジュールから ipcMain と ipcRenderer への移行ipc
モジュールが非推奨になった。代りに Main プロセスは ipcMain、Renderer プロセスでは ipcRenderer を使用する。
const ipcMain = require( 'electron' ).ipcMain;
ipcMain.on( 'asynchronous-message', ( ev, arg ) => {
console.log( arg ); // prints "ping"
ev.sender.send( 'asynchronous-reply', 'pong' );
} );
ipcMain.on( 'synchronous-message', ( ev, arg ) => {
console.log( arg ); // prints "ping"
ev.returnValue = 'pong';
} );ipcRenderer はイベント ハンドラも変更されている。従来は
ipc.on( 'message', ( arg ) => {
} );となっていたが新ハンドラは第一引数にイベント オブジェクトを取る。インターフェース設計が Main/Renderer プロセスで統一されて分かりやすくなった。
ipcRenderer.on( 'requsetMessage', ( ev, arg ) => {
ev.sender.send( 'responseMessage', 'I am a Renderer' );従来は Renderer プロセスのハンドラから Main プロセスに返信したいなら通常の send を利用していた。新ハンドラでは Main プロセスと同様にイベント オブジェクトの sender 経由で直に返信できる。
BrowserWindow のオプションと API 名の変更
BrowserWindow のオプション名から - が取り除かれた。例えば max-width は maxWidth になっている。リファレンス を確認すると chain-case だったものは camelCase へ改められたようだ。chain-case だと JavaScript のオブジェクト名をクォートする必要があり面倒。また chain-case とそうではないものがオブジェクト内に混在しているときにクォートで統一すべきか悩んだものだが、こうした問題が解消された。
API 名の Url という表記が URL に変更されている。代表的なものだと BrowserWindows の loadUrl が loadURL になった。
BrowserWindow の新しいオプション名については - で検索してリファレンスを確認しながら置き換えてゆく。API 名については loadUrl の場合、非推奨とマークされているようで警告される。とはいえ、全 API がこうなっているか分からないので Url で検索して個別対応するのが無難だろう。
特殊フォルダーの追加
app.getPath で取得可能な特殊フォルダーが大量に追加された。これらはプラットフォーム標準のファイル置き場。ファイル操作の際 dialog.showOpenDialog の defaultPath へ指定するなどの用途が考えられる。
リファレンスにキー単位でフォルダの解説が掲載されているけれど、現時点では Windows のものだけ。よって実際に得られるパスを調べるため、Main プロセスで以下の関数を実行してみた。
function getPathSample() {
console.log( 'documents:', App.getPath( 'documents' ) );
console.log( 'downloads:', App.getPath( 'downloads' ) );
console.log( 'music:', App.getPath( 'music' ) );
console.log( 'pictures:', App.getPath( 'pictures' ) );
console.log( 'videos:', App.getPath( 'videos' ) );
}OS X El Capitan 10.11.1 上の実行結果は以下。XXXX 部分はログインしているユーザー名。
documents: /Users/XXXX/Documents
downloads: /Users/XXXX/Downloads
music: /Users/XXXX/Music
pictures: /Users/XXXX/Pictures
videos: /Users/XXXX/MoviesWindows 8.1 での実行結果は以下となった。
documents: C:\Users\XXXX\Documents
downloads: C:\Users\XXXX\Downloads
music: C:\Users\XXXX\Music
pictures: C:\Users\XXXX\Pictures
videos: C:\Users\XXXX\VideosOS X と Windows ならば追加されたフォルダーすべてのパスを得られた。Linux は試していない。Linux はディストリビューション間で特殊フォルダーの定義が統一されているも不明なのでパスを得られないかもしれない。
その他
その他の変更はバグ修正や普段あまり使わない機能に関するものなので割愛。
サンプル プロジェクト
今回の対応を実施したサンプル プロジェクトを公開。