Skip to main content

Electron Getting Started Guide

Free2017-09-17#Tool#electron系统托盘#electron状态栏icon#electron桌面通知#electron ETIMEDOUT#electron mac

Starting Electron from 0.2

I. Understanding

Positioning

Electron is a framework for creating native applications with web technologies like JavaScript, HTML, and CSS.

Implementation

Electron = Node + Chromium + V8

These are just Electron's dependencies. The most critical part for cross-platform is naturally the adaptation layer, completed by C++ modules callable by node, providing system-level platform interfaces

Applicable Scenarios

It may be difficult to smooth out differences in desktop environments. Most of Electron's APIs are platform-specific, for example, in quick start:

// Quit when all windows are closed.
app.on('window-all-closed', function () {
  // On OS X it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

If you want to use Electron to achieve perfect cross-platform consistent experience, it still takes considerable effort, and even some aspects are impossible to make consistent (may need to make some C++ modules yourself to complete adaptation). From the API experience perspective, it's more laborious than ionic mobile cross-platform, with too many platform differences

But if you just want to "use JS to write a Mac/Win tool, maybe it can even be cross-platform", that is, without considering platform differences, Electron is still quite good

II. Development Environment

quick start

Official provides quick-start, considered a basic trial environment:

# Clone this repository
git clone https://github.com/electron/electron-quick-start
# Go into the repository
cd electron-quick-start
# Install dependencies
npm install
# Run the app
npm start

May encounter ETIMEDOUT during npm install, because electron package is very large (120M):

node install.js

.../node_modules/electron/install.js:48
  throw err
  ^

Error: connect ETIMEDOUT 52.216.66.16:443
    at Object.exports._errnoException (util.js:1034:11)
    at exports._exceptionWithHostPort (util.js:1057:20)
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1096:14)

Recommend switching to taobao mirror for download:

# Delete the incomplete download
rm -rf node_modules/electron
# Specify taobao mirror
ELECTRON_MIRROR=http://npm.taobao.org/mirrors/electron/ npm install electron

If everything is normal, a hello world window should appear. Check the API documentation, experience some system native APIs, such as system tray, desktop notifications, etc., trial ends

If planning to start working on it, strongly recommend not starting from quick start, because it's missing many things:

  • Modularization solution

  • Build solution (development-package-release)

  • Component library (UI library)

  • Route management

  • Persistence solution

Then may need react, webpack, antd, react-router, xxx-storage and many other things. Doing it manually, just the webpack build solution takes half a day, so we need more powerful template projects

boilerplate

For react family bucket, here recommend two project templates:

  • electron-react-boilerplate: yarn manages dependencies, webpack builds

     React
     Redux
     React Router
     Webpack
     React Transform HMR
    
  • electron-react-redux-boilerplate: npm manages dependencies, npm scripts builds

     React Router
     Redux Thunk
     Redux Actions
     Redux Local Storage
     Electron Packager
     Electron DevTools Installer
     Electron Mocha
     Browsersync
    

webpack configuration build has better scalability, but actual use found electron-react-boilerplate build configuration is quite complex, couldn't run locally, gave up after trying to resolve without success, switched to electron-react-redux-boilerplate

Both templates do not provide UI component library, after introducing antd found npm scripts build script is difficult to solve the problem of automatically importing css (webpack can add loader to solve), temporarily use cp to hold on, consider switching to webpack later:

"private:style": "cp -f node_modules/antd/dist/antd.css build/antd.css; cp -rf app/css build/css"

P.S. When installing dependencies, will also encounter electron download timeout problem, similarly, environment variable points to taobao mirror:

ELECTRON_MIRROR=http://npm.taobao.org/mirrors/electron/ yarn

III. Common Problems

1. Make window stick directly below tray icon

There's an existing module, quite easy to use:

First get the position of tray icon, then calculate centering based on window size

2. System tray icon size

For OS X, create icons:

icon.png (for best results aim 16x16px)

icon @2x.png (32x32px)

For Windows, create single icon:

icon.ico

ICO format will work better than classic PNG. If you want PNG, make it 32x32px.

From: Proper tray icon

Mac top menu bar height is 22px, can use 22px or 16px png format icon

P.S. gif format images cannot be used as icons

3. Mac system notification Chinese garbled text

HTML needs to set charset through meta:

<meta charset="utf-8">

Otherwise literal Chinese strings in external JS resources imported in HTML will appear garbled

4. Persistent storage

Recommend using electron-store

Store with JSON file, placed in application installation directory, API is not very scientific:

// set() can only store basic values
store.set('unicorn', 'ma');
console.log(store.get('unicorn'));
//=> 'ma'

// Storing object paths is inconvenient
store.set('foo.bar', true);
console.log(store.get('foo'));
//=> {bar: true}

// store can only replace all data entirely
store.store = data

Doesn't affect use much, read/write are synchronous, suitable for storing simple user configurations. For large amounts of data, there may be performance issues

P.S. For more Electron data storage methods please check [How to store user data in Electron](https://medium.com/ @ccnokes/how-to-store-user-data-in-electron-3ba6bf66bc1e)

5. IPC

There are two processes in Electron, Main and Renderer, the former is responsible for managing everything and interacting with the platform, the latter provides browser environment, rendering pages

Inter-process communication support is relatively good, with synchronous and asynchronous两种方式, communicating through event messages

Asynchronous communication (event.sender.send()):

// In main process.
const {ipcMain} = require('electron')
ipcMain.on('asynchronous-message', (event, arg) => {
  console.log(arg)  // prints "ping"
  event.sender.send('asynchronous-reply', 'pong')
})

// In renderer process (web page).
const {ipcRenderer} = require('electron')
ipcRenderer.on('asynchronous-reply', (event, arg) => {
  console.log(arg) // prints "pong"
})
ipcRenderer.send('asynchronous-message', 'ping')

Synchronous communication (event.returnValue):

// In main process.
const {ipcMain} = require('electron')
ipcMain.on('synchronous-message', (event, arg) => {
  console.log(arg)  // prints "ping"
  event.returnValue = 'pong'
})

// In renderer process (web page).
const {ipcRenderer} = require('electron')
console.log(ipcRenderer.sendSync('synchronous-message', 'ping')) // prints "pong"

P.S. If parameter sent from renderer is undefined, directly passing to system interface, may encounter error:

ERROR:v8_value_converter.cc(374)] Unexpected v8 value type encountered.

Parameters passed to system interface should be strictly validated to avoid such problems

6. Auto-start on boot

There's an existing module: node-auto-launch

npm install --save auto-launch

P.S. Mac indeed adds a startup item, but not checked, may need to specify application path, wait for further understanding

Written at the end

Actually, dependency on system-level APIs is far less than imagined. Most learning cost comes from frontend ecosystem (React family bucket), completely satisfactory component library doesn't exist

Things are not yet in shape, continue next week

Comments

No comments yet. Be the first to share your thoughts.

Leave a comment