Real World Electron Development
~ Case of the Kobito, Markdown Editor for YAPC Hackathon!
@mizchi / Koutaro Chikuba, Increments
- Node.js / Frontend Engineer
- Single Page Application Specialist
- Kobito for Windows Developper
- Increments, Inc (Providing qiita.com / Qiita:Team)
- Sorry, my English is not so good.
ここから日本語
ここで喋ることは一昨日急に決まったので(YAPC回るし)スライド作る時間なかった。ゆるして。
Markdown Editor デモ
- Web系の会社がWPFに習熟したエンジニア雇うのは難しい
- nodeの豊富なライブラリ資産
- 環境固定でエッジなAPIでコードを書ける
- IndexedDb
- WebComponents
- ServiceWorker
- Chrome以外の動作確認をサボれて最高
- 発生した問題がnode/ブラウザのどちらかの問題か特定するだけの知識
- Electronのバグ!っていう前にChromeのバグを確認
- Issues - chromium - An open-source project to help move the web forward. - Google Project Hosting
- Electronのバグ!っていう前に各npmパッケージのIssuwを確認
- Electronの質問です!って言いながらブラウザ/nodeの質問しにくる人多すぎて、関係者はイライラしていると思う!!!!!
- あるとよい: nodeでの開発経験
- nodeできることならなんでもできる
- nodeで足りない機能はC++とV8 BridgeでAPI書く必要
- だいたいある
- あるとよい: ブラウザフロントエンドの経験
- Single Page Applicationのノウハウ
- ユーザーはElectronだからUIがHTMLでレスポンスが悪い、なんてのを許容しない
- => 必然的にSPA
- (業務アプリだと気にしないかも)
- HTML = GUI Toolkit
- Single Page Applicationのノウハウ
- 確かにElectronの環境に依存したバグは存在する
- node/browser対応のjsで
if (typeof global === 'object') {...}
としてしまっているケース- 適当にforkしたりパッチ当てたりして対応(これは難しくない)
- 一部のnativeモジュールのビルド(一時期sqlite3落ちてて困った)
- webview tagはよくバグってる
- node/browser対応のjsで
- これどうやって実現するの?
- HTTP Request の例
- XMLHTTPRequest / Fetch API
require('http')
- ※ クロスドメイン制約は起動オプションで変更できる
- modal window
- Electron組み込みmodal popup
- DOMでcssでposition: absolute
- 場合によっては
input<type='file'/>
- ストレージ
- IndexedDb / localStorage
- HTML5 File API
require('fs')
や sqlite3のORM- ネイティブモジュールを使うと各環境でnpm install しなおす必要があったので自分はIndexedDbを使った
- HTTP Request の例
- コミットログみると開発者はzcbenz氏ほぼ一人
- ほとんど C++(chromium-srcへのパッチ)
- node v8 とのバインディングで少しだけJavaScript(coffee)
- Electron では node v8 と Chromium のメインループの統合処理が主
- ChromiumのStandalone化だけなら atom/brightray 側を読む
- nwjs/nw.js
- セキュリティサンドボックスモデルが違う
- あるインスタンスがnode由来のオブジェクトか、ブラウザ由来のオブジェクトかを厳密に区別する
- Electronは区別せずシンプルで楽観的
- 構成的に複数ウィンドウは出せない
- adobe/brackets-shell (no node.js)
- bracketsというエディタのシェル
CEF3-based application shell for Brackets.
ソース公開されてないけど、たぶんVivaldi も似たような構成なんじゃないか?
- 最初一部のウイルス検知ソフトウェアで引っかかった(symantic)
- 問い合わせて問題がないことを確認して解除してもらった
- 胃に悪い
- App Storeに出せない
- Mac App Store · Issue #249 · atom/electron
- nodeの一部がMacOSXのサンドボックス違反?
- nw.js と共通の問題
- パッチはあるけど大変 Electron for the Mac App Store
There will probably be a 2nd version of Electron OS X posted for future releases that is MAS compatible
とのこと。future っていつ頃?
- resedit.exeでプロセス名やアイコンを変えれる、とあったが自分はできなかった
- ついでにいろいろイジって回りたかった(IndexedDbの最大サイズとか)
- 適当に作るだけなら不要
- 定期的にHEADが落ちてる
- テスト通ってても特定プラットフォーム(Windowsでだけ)壊れてたりする
- node / io.js のゴタゴタでリポジトリのurl変わって落ちたりもした
- Issue建てて壊れてんぞーって言うと直る(こともある)
- webview tag まわりは壊れがち
- electron/web-view-tag.md at master · atom/electron
- webview tag 自体は Chrome拡張用の機能で、Electron側で機能を追加している webview Tag - Google Chrome
- webviewタグを使った場合、必ずビルドごとに挙動を確認すること!
- 他にも秘孔あるかも
-
atom/atom
- bootstrap ~ window生成 ~ apmのplugin読み込み までは難しくない(コード量は多いが)
- 編集バッファのコードを読むのは難しい(コードハイライター + DOM職人芸的な最適化)
- 困ったらatomインスタンスのAPI探す atom/atom.coffee at master · atom/atom
-
benogle/curve-app
- 一昨日の発表で知った
- 昨日というよりAtom開発者ならではのビルド環境
- package.json の devDependencies を真似たい
- どんな環境でも動くJavaScript、という考え方
- Pure EcmaScript Implementation
- 強制的にView触れないので、DDDにおけるdomain層の設計ギプスと考えればよい
- 環境ごとの制約を満たせばいつでもいろんなプラットフォームで展開できる
- 手元に複数の実装がある
- Electron - Mac / Win / Linux(Debian)
- npm版(electron-prebuilt)
- ブラウザ版 (Chrome / Firefox / Edge で動作確認)
- Chrome Packaged Apps
- 必要になったタイミングで必要な物をリリース可能
- E2Eテストでselenium組み込みが面倒なときにブラウザ版で走らせたりした
- 手元に複数の実装がある
main.jsの
var BrowserWindow = require('browser-window')
は、クライントでの
var BrowserWindow = require('remote').require('browser-window')
と同じ。その気になればブラウザ側から別ウィンドウの生成まで可能
- kobito は production では browserify を使うようにしている
- 小サイズ化(87MB -> 1.8MB)
- (ちょっとした難読化)
- browserify できないモジュールは無視する
- ポリフィルできない fs, http 等
- Electron プリインの app, browser-window, ipc ...
- global.require('...') と書いて解決(BK気味)
- 開発時はbrowserifyの時間をスキップしたかったんでそのまま
- いまは 差分ビルドできる watchify あるんで問題ないかも
- (たぶん) atom shell archiver
- tar のようにファイルを連結する(だけ)
- Electronのfsモジュールは中からは foo.asar/index.html と中のパスを透過的に扱える
- fsにはその為のパッチが当たっており、
require('original-fs')
で元のfsを使うことも可能
main.js
versions/
- 1.1.0.asar
- index.html
- etc...
- 1.0.0.asar
- index.html
- etc...
起動後にバージョンサーバーを確認して、存在しなければ asar をダウンロードして再起動。
atom/Electron/docs 以下を穴があくほど読め!以上!