Writing

Desktop application

with

Electron?

Electron?

  • Chromium + NodeJS
  • Cross-platform desktop application framework

Why Electron?

  • Build cross-platform application with less effort
    • macOS, Windows, Linux
  • Code with web technologies - HTML, CSS, JavaScript
  • NO cross-browsing support code required!
  • Active community
  • Great Documentation

Modern!

  • Uses recent version of Chrome
  • Chrome 58.0.3029 (@Electron 1.7.5)
    • ES6 coverage: 97%
    • ES2016+ coverage: 81%
  • Node 7.9.0
  • V8 5.8.283.38

Supported platforms

  • macOS 10.9+
  • Windows 7+ (both x86 and x64)
  • Linux (both x86 and x64)
    • ​Ubuntu 12.04+
    • Fedora 21+
    • Debian 8

Apps built on Electron

  • Atom
  • Visual Studio Code
  • Slack
  • GitHub Desktop
  • GitKraken
  • Remember
  • ... and ProtoPie!
  • https://electron.atom.io/apps/

Quick look

Quickstart

  • Electron API Demos
    • https://github.com/electron/electron-api-demos
$ git clone https://github.com/electron/electron-api-demos
$ cd electron-api-demos
$ npm install
$ npm start

REPL

$ npx electron --interactive
> const electron = require('electron');
> const win = new electron.BrowserWindow({width: 800, height: 600});
> win.loadURL('https://m.naver.com');

 not available on Windows :-(

Process structure

  • Renderer
    • Chromium + NodeJS + Electron API
  • Main
    • NodeJS + Electron API

Packaging

Manual build

  • Tar all source / resource files with asar
    • place app.asar into resources directory
  • Change app icon and metadata
    • macOS - edit Info.plist
    • Windows - edit electron.exe with rcedit

 

=> Self-executable electron app

electron-builder

  • Cross-platform build tool
  • Code signing (macOS, Windows)
  • Auto update ready application packaging
  • Supports installer target
    • dmg, pkg, mas, deb, rpm, apk, nsis, portable, Squirrel.Windows, AppX

TODO: github 예제에 electron-builder 설정 추가할 것

Code signing (macOS)

  • Download the certificate from Apple dev center
  • Import certificate into keychain
  • Add Codesign privilege to the certificate
  • export env variable CSC_NAME
  • electron-builder will use the cert automatically

Code signing (Windows)

  • Buy a codesign certificate from any CA
  • Import the cert into Cert manager
  • use signtools to sign executables and dlls 
    • Bundled in Visual Studio and Windows SDK

Use a EV certificate (Win)

  • Non-EV cert will cause SmartScreen filter alert
  • Sufficient reputation points are required to avoid alerts.
  • Reputation points will be reset for each new version

Source Code Protection

zeit/pkg (former EncloseJS)

  • Transforms JavaScript code to native binary using V8 internal compiler
  • Generates self-executable binary
PROJECT_ROOT
├─node_modules
└─src
    ├─client
    ├─electron
    └─server
PROJECT_ROOT
├─node_modules
└─output
    ├─client
    ├─electron
    └─server.exe

Notes:

  • 외부 파일 경로 접근법이 달라짐
  • asar 도 마찬가지 (=> 확인할것)

Auto Update

Limitations of built-in update

  • 업데이트 체크만으로도 다운로드가 자동 개시됨
  • 업데이트 다운로드 진척을 알 수 없음
  • 중간에 취소할 수 없음

TODO: translate

Introduced an update broker

  • Provides download progress
  • Verify download checksum
  • Runs a local HTTP server to respond to autoUpdater

1. Check for update

2. Download

3. Set local feed url

4. Download Update

electron-updater

  • Supports staged rollouts
  • Provides download progress event
  • Well integrated with electron-builder

Case study:

Platform limitations and workarounds

Menu is read only

  • 메뉴의 항목을 동적으로 추가하거나 레이블을 변경할 수 없음
  • 변경하려면 메뉴 전체를 다시 빌드해서 교체해야 함

Clipboard

  • Supported formats: Text, HTML, Image 
  • Limitation
    • No support custom format
    • Large clipboard data degrades performance
  • Solution
    • Virtual clipboard + clipboard key
    • write dirty log to tolerate system shutdown

Proxy

  • NodeJS는 시스템 proxy를 자동으로 사용하지 않음
  • Electron은 독자적인 net 모듈을 제공
  • Chromium의 native networking library
    • 시스템 proxy설정을 가져옴
    • 프록시 인증 (basic, digest, NTLM, Kerberos..) 을 지원
    • 트래픽 모니터링 프록시 지원 (like Fiddler)

Case study:

ProtoPie
architecture design considerations

Transparent server API

  • Domain logic must not be placed in client code
    • code protection introduces complex comm. structure

Client - Electron - Server

Transparent server API

  • Add ipc tunnel between client and server
    • Client can send event to server

TunnelClient - TunnelBridge - TunnelServer

Transparent server API

  • Server builds API data from decorator metadata
  • Client inflates virtual API from server sent data
  • client에 대한 Server API 공개 범위를 조절할 수 있음
export class CommandHistory {
    @CallbackApi
    public undo(): void {
    }

    @ListenerApi
    public on(eventType: string, callback: Function): void {
    }    
}
const commandHistory = new CommandHistory();
virtualApi.addService('history', commandHistory);
const server = new VirtualApiClient(tunnelClient);
$("#undo_btn").on("click", () => server.history.undo());

Command history

  • Undo / Redo / Copy / Paste / Multi-select
    • "Change set" should be defined
  • Idempotece of command
    • Every modification should be restored in reversed order 

Command history

  • Undo / Redo / Copy / Paste / Multi-select
    • "Change set" should be defined
  • Idempotece of command

Command

Event Listeners + Query APIs

Model

UI

UI

UI

Model

export class Layer {
    @Watch
    x = 0;

    @Watch
    y = 0;
}
server.command("layer_edit", layerId, {x: 10, y:20});
server.layers.on('change', (layer, prop, newValue, oldValue) => {
    this.element.style.left = layer.x + 'px';
    this.element.style.top = layer.y + 'px';
});

Virtual API

  • Build server API in client with metadata
    • No API code exists in client side
  • Client code can access server API as same as client code
export class CommandHistory {
    @CallbackApi
    undo() { ... }

    @CallbackApi
    redo() { ... }

    @ListenerApi
    on(eventType, callback) { ... }
}
this.apiServer.addService('history', new CommandHistory(context));
server.history.on('undostackchange', (undoCount, redoCount) => {
   ...
});
server.history.undo();

Context

  • Multi-window application can have 2 types of context
    • Whole application
      • DeviceConnectionManager
      • LicenseManager
    • Per-window (in protopie, it is called Authoring Context)
      • ModelRoot
      • CommandHistory
      • TemporaryDirectory

Context

TODO: Add diagram

Writing Desktop application with Electron

By gloridea

Writing Desktop application with Electron

  • 974