electron vueでデスクトップアプリを作る



結論

作れる。


作った


Electronとは

html/js/cssを使ってネイティブデスクトップアプリケーションが作れます。
当然 web frontendの構成を利用できるので、ReactやVueの恩恵を受けることも可能です。

IEではWebRTCが動かないので、デスクトップアプリを作ることでこれに対応できるかを調査しました。


どういうときにDesktopアプリを作る?

  • PCに常駐させたい
  • Chromeが諸事情でインストールできないweb app
  • 作りたいからしょうがない!

構成と仕組み

ネイティブ層 -> WebApp層(Chromium) みたいな感じで、「Chromiumブラウザを呼ぶブラウザアプリケーション」と理解してもらえるといいと思います。

Inter-process Communicationと呼ばれるプロセス間通話でこの2層で情報をやり取りします。
あとはWebApp側でひたすらSPAが動く感じですね。


以下にすぐ動かせるサンプルを置きます。
https://github.com/bdero/electron-vue-typescript-starter

RJ-MN-367.local ^_^  ~/Documents/web/electron-vue-typescript-starter (master)
% tree                                                                                                                            [12:39:49]
.
├── LICENSE
├── README.md
├── _compilerc
├── forge.config.js
├── package.json
├── src
│   ├── components
│   │   └── App.vue
│   ├── index.jade
│   ├── main.ts
│   └── render.ts
├── tsconfig.json
├── tslint.json
└── types
    └── vue-module.d.ts

このサンプルではHTMLの簡略化にjadeを使っています。またvue.js/typescriptを使っているいいサンプルです。

懸念

既存のSPAのソースを載せられるか?

一部は可能であるが、現状PHP上に乗る前提で実装されているため、API側がこれに対応できていない。
- ログインをSPAとして実施できる仕組み
- 外部からAPIを叩ける口を用意する

対応が必要になる。まぁこれはできる。


実装にクセは?

とくにない。ネイティブ部分だけ独特のライフサイクルや本番ビルド時の懸念はある。
例えばdev時はlocalhostに擬似的にweb serverが立ち上がってアクセスされるが本番ビルド時はfile://アクセスになったり。


簡単?

簡単です。フロントエンドの経験あればちょろいです。
(win向けのパッケージングだけ、macでやるならwineなどを入れる必要があるので注意)


SkyWayとの連携

skyway-jsはnpmから利用できるskywayのweb用のライブラリである。
これを組み込む事は既存研究により可能であることが立証されている。

Electronで手軽にSkyWayを使う

ElectronでSkyWayを使う場合、問題になるのがXHR等でリクエストを投げる時、リクエストヘッダーにOriginフィールドがないまたはOriginフィールドの値が"file://"(WebSocket)になるということ。
SkyWayでは(APIキーごとに)登録したドメインからしか接続が行えない仕組みとなっていますが、ドメインの判定をこのリクエストヘッダーのOriginフィールドで行っているため、なんの対処をせずにSkyWayのプログラムを組んだElectronアプリで接続しようとするとどうしてもはじかれてしまいます。

という注意点が報告されているが最新の skyway-js では問題なさそうに見えた。
もし問題があっても、ネイティブ層で特定の実装で回避できるので問題ない。


画面共有したい

skywayの画面共有はライブラリが公開されている。一方でこのライブラリを使う場合は、Chrome拡張が必要になる、chrominiumをベースにしているelectronでも必要になる。

最初は「BrowserWindow.addDevToolsExtensionを使えばいけるじゃん!」と思ってたけど、これはサポートされたExtensionのみ・・・

このラブラリは利用できない可能性が高い・・・

ただWebRTCを使ったElectronによるScreen Shareに関してはscreencatというプロジェクトがあり、実現はできているので要調査。

2019/11/05 追記
今時点ではいけそう。

Since Chrome 72 and Firefox 66, navigator.mediaDevices.getDisplayMedia() is available. You can get the screen stream through this API without any dependencies.

今はおそらくいける。


vuexとの連携

みんなご存じ、vuexではstateと呼ばれる形で値を管理してこれの変更を同期したりいい感じ使うことで状態を管理する。
このstateで管理された値を外部から変更する場合、特定の箇所からの変更(mutation)のみ許容している。

const store = new Vuex.Store({
  state: {
    peer: new Peer(xxxx)
  },
  mutations: {
  }
})

そのため、上記のようなことをしようとすると new Peerは自身を内部的に解放したりするので ** Do not mutate vuex store state outside mutation handlers.** と怒られる。そのためやむなく

import Skyway from '../class/skyway'
import { SKYWAY_API_KEY } from '../config'

Vue.use(Vuex)

export default new Vuex.Store({
  modules,
  plugins: [
    ...
  ],
  strict: process.env.NODE_ENV !== 'production',
  getters: {
    skyway: () => {
      return new Skyway(SKYWAY_API_KEY)
    }
  }
})

こんな感じでglobal singletonみたいになった。悲しい。


配布

パッケージマネージャーが配布されており、バイナリの生成が可能

 $ # electron-packager <sourcedir> <appname> --platform=<platform> --arch=<arch> --version=<version>
$ electron-packager ./sample sample --platform=darwin,win32 --arch=x64 --electronVersion=0.36.1

これにより.exe, .appファイルを作ることがでいるので、あとはこれを配布すればいい。
ビルド時に暗号化も走らせることができるのでリバースの心配も少ないが、少ないというだけで懸念はあるしネットワークも見れちゃうだろうので検討は必要。

また製品版としてMacで配布したい場合はちゃんと有料アカウントが必要です。


結論

  • 作れる
  • vuexとの連携はちょっと工夫がいる
  • 画面共有は難しそう
  • ブラウザと違ってバージョン固定できるので楽そう
  • 配布も楽そう
  • でも実際やると地雷多そう

というイメージでdone