Skip to content

Instantly share code, notes, and snippets.

Created August 22, 2015 14:48
Show Gist options
  • Save anonymous/04ad6b4d77fe4462e8a6 to your computer and use it in GitHub Desktop.
Save anonymous/04ad6b4d77fe4462e8a6 to your computer and use it in GitHub Desktop.

Real World Electron Development

~ Case of the Kobito, Markdown Editor for YAPC Hackathon!

@mizchi / Koutaro Chikuba, Increments

About

  • 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回るし)スライド作る時間なかった。ゆるして。

Kobito とは

Markdown Editor デモ

Electron採用理由

  • Web系の会社がWPFに習熟したエンジニア雇うのは難しい
  • nodeの豊富なライブラリ資産
  • 環境固定でエッジなAPIでコードを書ける
    • IndexedDb
    • WebComponents
    • ServiceWorker
  • Chrome以外の動作確認をサボれて最高

Electronでの開発に必要な足腰

  • 発生した問題がnode/ブラウザのどちらかの問題か特定するだけの知識
  • あるとよい: nodeでの開発経験
    • nodeできることならなんでもできる
    • nodeで足りない機能はC++とV8 BridgeでAPI書く必要
      • だいたいある
  • あるとよい: ブラウザフロントエンドの経験
    • Single Page Applicationのノウハウ
      • ユーザーはElectronだからUIがHTMLでレスポンスが悪い、なんてのを許容しない
      • => 必然的にSPA
      • (業務アプリだと気にしないかも)
    • HTML = GUI Toolkit
  • 確かにElectronの環境に依存したバグは存在する
    • node/browser対応のjsで if (typeof global === 'object') {...} としてしまっているケース
      • 適当にforkしたりパッチ当てたりして対応(これは難しくない)
    • 一部のnativeモジュールのビルド(一時期sqlite3落ちてて困った)
    • webview tagはよくバグってる

Electronを使う場合、同じ目的に対して複数の回答がありうる

  • これどうやって実現するの?
    • 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を使った

Electron本体の構成を読む

  • コミットログみると開発者は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問題

There will probably be a 2nd version of Electron OS X posted for future releases that is MAS compatible

とのこと。future っていつ頃?

Electron を自前でビルドする必要があるか?

  • resedit.exeでプロセス名やアイコンを変えれる、とあったが自分はできなかった
  • ついでにいろいろイジって回りたかった(IndexedDbの最大サイズとか)
  • 適当に作るだけなら不要

Electronのビルドでの苦悩

  • 定期的にHEADが落ちてる
    • テスト通ってても特定プラットフォーム(Windowsでだけ)壊れてたりする
    • node / io.js のゴタゴタでリポジトリのurl変わって落ちたりもした
  • Issue建てて壊れてんぞーって言うと直る(こともある)
  • webview tag まわりは壊れがち

Electronアプリ開発において参考になる実装

  • atom/atom

    • bootstrap ~ window生成 ~ apmのplugin読み込み までは難しくない(コード量は多いが)
    • 編集バッファのコードを読むのは難しい(コードハイライター + DOM職人芸的な最適化)
    • 困ったらatomインスタンスのAPI探す atom/atom.coffee at master · atom/atom
  • benogle/curve-app

    • 一昨日の発表で知った
    • 昨日というよりAtom開発者ならではのビルド環境
      • package.json の devDependencies を真似たい

Isomorphic(Universal) JavaScript

  • どんな環境でも動くJavaScript、という考え方
    • Pure EcmaScript Implementation
    • 強制的にView触れないので、DDDにおけるdomain層の設計ギプスと考えればよい
  • 環境ごとの制約を満たせばいつでもいろんなプラットフォームで展開できる
    • 手元に複数の実装がある
      • Electron - Mac / Win / Linux(Debian)
      • npm版(electron-prebuilt)
      • ブラウザ版 (Chrome / Firefox / Edge で動作確認)
      • Chrome Packaged Apps
    • 必要になったタイミングで必要な物をリリース可能
    • E2Eテストでselenium組み込みが面倒なときにブラウザ版で走らせたりした

TIPS

remote

main.jsの

var BrowserWindow = require('browser-window')

は、クライントでの

var BrowserWindow = require('remote').require('browser-window')

と同じ。その気になればブラウザ側から別ウィンドウの生成まで可能

プロダクションでbrowserify

  • kobito は production では browserify を使うようにしている
    • 小サイズ化(87MB -> 1.8MB)
    • (ちょっとした難読化)
  • browserify できないモジュールは無視する
    • ポリフィルできない fs, http 等
    • Electron プリインの app, browser-window, ipc ...
    • global.require('...') と書いて解決(BK気味)
  • 開発時はbrowserifyの時間をスキップしたかったんでそのまま
    • いまは 差分ビルドできる watchify あるんで問題ないかも

asar

  • (たぶん) atom shell archiver
    • tar のようにファイルを連結する(だけ)
    • Electronのfsモジュールは中からは foo.asar/index.html と中のパスを透過的に扱える
    • fsにはその為のパッチが当たっており、 require('original-fs') で元のfsを使うことも可能

KobitoのUpdaterの実装

main.js
versions/
    - 1.1.0.asar
        - index.html
        - etc...
    - 1.0.0.asar
        - index.html
        - etc...

起動後にバージョンサーバーを確認して、存在しなければ asar をダウンロードして再起動。

その他諸々

atom/Electron/docs 以下を穴があくほど読め!以上!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment