7
3

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 1 year has passed since last update.

鈴鹿高専Advent Calendar 2021

Day 14

ElectronとNode.jsの制約に苦しめられた話

Last updated at Posted at 2021-12-13

注意事項

Electron初心者なので、間違った情報があるかもしれません。
タスクに追われてるので文章がちゃんとしていない可能性があります。
コードを引っ張り出してくるのが面倒だったので、コードは1行もありません!
ご了承ください。:bow:

バージョン情報

詳しくは覚えていないのでメジャーバージョンのみ
Node.js v16.x
Electron v15.x

経緯

Electronを採用した理由

  • ブラウザの技術でデスクトップアプリを作れるから
  • 実績がある(VSCode、Slackなど)
  • 並列処理もなんとかできると思ってた

あまり深く考えずにElectronを採用しましたが、これが原因で後々苦しむことになります...

Electronの仕様

Electronは起動時に2つのプロセスを立ち上げます。

メインプロセスとレンダラープロセスの2種類があります。(参考: https://www.electronjs.org/ja/docs/latest/tutorial/process-model)

また、プロセス間の通信にはIPC(プロセス間通信)を用います。
ElectronにはそのためのAPIが既に用意されています。

なぜこのような仕組みになっているかと言うと、1つのプロセスで様々なことをできるようにするとセキュリティ的によくないからです。
複数のプロセスに分けて、プロセスごとにできることを制限することでより安全にしています。

メインプロセスについて

Node.js上で動作し、アプリのウィンドウ管理やバックグラウンド処理等を行います。

何ができるか?

ストレージにアクセスしたり、コマンドを実行したり、ざっくり言うとネイティブのことはここでします。
また、

制約

自分がぶち当たった制約の中で印象深かったのは以下のとおりです。

  • メインプロセスで動作が停止すると、レンダラープロセスも停止します
    • 常時バックグラウンドで動き続けるような処理はメインプロセスではできないはず
  • ブラウザにあるようなプロンプトがセキュリティの関係上使えない
  • 並列処理が辛い

レンダラープロセスについて

Chromium上で動作し、ウェブベースのUIを提供します。

何ができるか?

ほとんど通常のブラウザとは変わりません。
追加の機能としては、メインプロセスと通信できるようにしてメインプロセスに定義したイベントを実行させることができます。
また、webviewタグを使用できます。

制約

自分がぶち当たった制約の中で印象深かったのは以下のとおりです。

  • セキュリティの関係上、デフォルトではNode.jsの機能を呼び出せない
    • nodeIntegration: trueにすればできる(昔のやり方、セキュリティ上よくない)
    • レンダラープロセスから分離したコンテキストに必要な機能をプリロードして使用する方法もある(新しいやり方、こっちを推奨してるっぽい)

その他

  • Electronでデータ保存するライブラリでまともそうだったのがほとんどJSONに保存するタイプだった
    • 本当はデータベースに保存したかった...

並列処理が本当に辛かった

上記の制約は全部なんとかすることができました。
ただし、並列処理だけは本当に辛かったです。

並列処理の方法ググってみた

色々ググったのですが、あんまりしっくりくる方法ではなかったです。

実際にどうしたか

上記のElectron公式ドキュメントにもある通り、Node.jsでもWeb Workerが使えます。
ただし、Web Workerでググってもあんまり参考になる情報がありません。
というのも、Node.jsのドキュメントを見るとworker_threadsというモジュールになっていて、Web Workerという呼ばれ方はされていないからです。

情報が少なかった上に、動作する保証がないのでこの方法で行くと決めるまでには2,3日かかりました...。

環境変数が使えない

まさかの環境変数が使えませんでした。
メインプロセスではprocess.env.NODE_ENVのようにすれば環境変数にアクセスできますが、新しく作ったスレッドには環境変数が何も格納されていません。

どうしたかというと、メインプロセスでスレッドを生やすときに環境変数を渡して、生やしたスレッドのprocess.envをオーバーライドしています。
脳筋ではありますが、メインプロセスから分岐したスレッドは別のJS環境として動いているのでこうするしかありません。

まとめ

苦労したーってことをひたすら書いただけの文章になってしまいましたが、まとめると以下のとおりです。

  • Node.jsでマルチプロセッシングするのはそこそこ辛いのでやめておいたほうがいい
  • Electronはウェブベースで凝ったデザインにできるけど、その代償として色々辛いことがある
    • 割と関連ライブラリがメンテナンスされてない
    • パフォーマンスが悪い
    • 回りくどいところがある
    • CSS辛い
  • 正直、ウィジェット・ツールキットやそのラッパーを使って作るのが楽

Node.jsは色んなことができて汎用性が高いのはそうなんですが、こういう問題にぶち当たるので適切な言語・フレームワーク等を用いたほうがいいなと思った(戒め)
みなさんも技術選定には気をつけてください。ゴリ押しでなんとかなることもありますが、かなり辛いです。

7
3
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
7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?