Electron 跨平台应用开发入门

本文由 Deguang 发表于 码路-技术博客html

Tips:前端

  • Electron 介绍
  • Electron 环境搭建
  • 进程通讯
  • 调用系统 API

Write once, run anywhere.
Sun 公司 Java 介绍词。

端的跨平台实现方案有哪些?

  • Web(浏览器)
  • 移动端设备:Hybrid(混合)、React Native、Weex、Flutter
  • 桌面端:NW.js、Electron、Flutter(~1.0)

Electron

1. 什么是 Electron

Electron 是由 Github 开发,用 HTML,CSS 和 JavaScript 来构建跨平台桌面应用程序的一个开源库。 Electron 经过将 ChromiumNode.js 合并到同一个运行时环境中,并将其打包为 Mac,Windows 和 Linux 系统下的应用来实现这一目的。

开发者只要使用 Web 技术完成业务部分便可,这就是对前端开发者最友好的地方。node

2. Electron 应用结构

Elctron 应用运行时,分为 主进程渲染进程ios

主进程 (Main Process)

  • package.json 中定义的 main 脚本运行的进程,被定义为 主进程,一个 Electron 应用有且只有一个主进程。
  • 主进程能够建立 Web 页面窗口,并传入 URL 加载网页做为图形界面。

渲染进程 (Renderer Process)

  • Electron 的每一个页面都有它本身的进程,叫作渲染进程。每个渲染进程都是独立的,只关心它所运行的页面;

进程通讯(IPC, Inter-Process Comminication)

Electron 不容许渲染进程调用系统 GUI 的原生 API,例如打开文件选择之类的系统操做,这种对系统 API 的调用只容许存在与主进程中。渲染进程,也就是页面调用 系统 API,须要由主进程担任桥梁的做用,来完成操做并获得返回结果。这里有两种方式能够实现进程通讯:git

使用 ipcRenderer 和 ipcMain 模块通讯

  • ipcRenderer

    ipcRenderer 是从渲染进程到主进程的异步通讯,可使用它提供的一些方法从渲染进程发送同步或异步的消息github

  • ipcMain

    ipcMain 是从主进程到渲染进程的异步通讯,处理从渲染进程发送出来的异步和同步信息,web

// renderer process
const {ipcRenderer} = requier('electron')

// async
ipcRenderer.on('PICK_FILE_CALLBACK', (event, arg) => {
    console.log(arg) // files
})
ipcRenderer.send('PICK_FILE')

// sync
ipcRenderer.sendSync('PICK_FILE_SYNC') // files
// main process
const {ipcMain} = require('electron')

// async
ipcMain.on('PICK_FILE', (event, data) => {
    // do something ...
    event.sender.send('PICK_FILE_CALLBACK', 'files')
})

// sync
ipcMain.on('PICK_FILE_SYNC', (event, data) => {
    // do something
    event.returnValue = 'files'
})
more: ipcRendereripcMain
  • ipcMainipcRenderer 又是什么?
ipcMain 和 ipcRenderer 都是 EventEmitter 类的一个实例。 EventEmitter 类是由 NodeJS 中的 events 模块定义、导出的。

EventEmitter 类是 NodeJS 事件的基础,实现了事件模型须要的接口, 包括 addListener,removeListener, emit 及其它工具方法. 同原生 JavaScript 事件相似, 采用了发布/订阅(观察者)的方式, 使用内部 _events 列表来记录注册的事件处理器。sql

使用 remote 进行 RPC 通讯

在渲染进程中使用主系统模块。chrome

// 渲染进程中
const { BrowserWindow } = require('electron').remote
let win = new BrowserWindow({width: 600, height: 400})
win.loadURL('https://github.com')
  • remote 对象

remote 模块返回的对象表示主进程中的一个对象,调用远程对象、远程函数时,至关于发送同步进程信息。let win = new BrowserWindow({width: 600, height: 400}),至关于在主进程中建立了一个 BrowserWindow 对象,而后在渲染进程中返回了相应的远程对象。数据库

more: remote

3. API

Electron API

Electron 提供了大量 API 以优化桌面应用开发体验。

Electron API 都有指派进程类型(文档中标记):只能用于主进程( BrowserWindow)、只能用于渲染进程( remote) 和 两种进程中都可使用。

Node.js API

Electron 同时在主进程和渲染进程中对Node.js 暴露了全部的接口

  • 原生 API
// Native API
const fs = require('fs')
fs.readFile(...)
  • 第三方 Node.js 模块
npm install -save axios
const axios = require('axios')

axios.interceptors.request(...)

4. 第一个 Electron 应用

环境依赖:Node.js && Npm (Yarn)

推荐使用 yarn 构建 Electron,使用 npm 大几率出现依赖安装失败的状况

起步

0.0.1 建立 demo 目录,执行 npm init,配置启动脚本 "start": "electron ."

// package.json

{
  "name": "demo",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "scripts": {
    "start": "electron ."
  },
  "author": "",
  "license": "ISC"
}

0.0.2 建立 main.js && index.html

➜  demo tree
.
├── index.html
├── main.js
└── package.json

0.0.3 安装 Electron

npm install --save-dev electron

0.0.4 建立一个窗口:

// main.js
const { app, BrowserWindow } = require('electron')

let win

function createWindow() {
    win = new BrowserWindow({ width: 600, height: 400})
    win.loadFile('index.html')
}

app.on('ready', createWindow)
<!-- index.html -->
<body>
    <h1>Hello, Electron.</h1>
    Node.js: <script>document.write(process.versions.node)</script>;
    Chrome: <script>document.write(process.versions.chrome)</script>;
    Electron: <script>document.write(process.versions.electron)</script>.
</body>

0.0.5 执行 npm run start,便可打开一个窗口,显示 Hello, Electron.

0.0.6 更新main.js,尝试更多功能:

// main.js
const { app, BrowserWindow } = require('electron')

let win

function createWindow() {
    win = new BrowserWindow({ width: 600, height: 400})
    win.loadFile('index.html')

    win.webContents.openDevTools()

    win.on('close', () => {
        // 关闭窗口、清空 win 对象
        win = null
    })

    app.on('window-all-closed', () => {
        // macOS 应用一般关闭窗口仍是保活的,只有使用 cmd + q 强制退出
        if (process.platform !== 'darwin') {
            app.quit()
        }
    })

    app.on('activate', () => {
        // macOS 点击 dock 图标而且没有其余窗口打开时,从新建立一个窗口
        if (win === null) {
            createWindow()
        }
    })
}

app.on('ready', createWindow)

0.0.7 从新执行 npm run start 启动应用。


more: 更多 Electron API 使用,能够尝试官方 electron-api-demos

打包应用

electron-packager

# 安装 electron-packager
npm install electron-packager --save-dev
# 基本命令
electron-packager <sourcedir> <appname> --platform=<platform> --arch=<arch> [optional flags...]
# 例如:
# electron-packager ./ demo --out ./dist --app-version 1.0.0 --overwrite

参数说明:

  • sourcedir:项目路径
  • appname:应用名称
  • platform:构建平台的应用(Windows、Mac 仍是 Linux)
  • arch:x8六、 x64 仍是两个架构都用
  • optional options:可选选项

为了更方便的构建,在 package.json 增长构建脚本

"package": "electron-packager ./ demo --out ./dist --app-version 1.0.0 --overwrite"

执行 npm run package

more: electron-packager

electron-builder

# 安装 electron-builder
npm install electron-builder --save-dev
// package.json 增长以下配置
"build": {
    "productName": "xxx",
    "appId": "com.xxx.xxx"
},
"scripts": {
    "dist": "electron-builder"
}

执行 npm run dist,完成打包

more: electron-builder

ps:mac 跨平台 打包 win32 须要 wine

客户端数据库

Electron 应用能够在本地使用客户端数据库,来维护本地数据,进行相应的 CURD 操做,下面是经常使用的一些轻量级数据库:





参考文档: