Electron 快速入门

简介

Electron 是一个可使用 Web 技术如 JavaScript、HTML 和 CSS 来建立跨平台原生桌面应用的框架。借助 Electron,咱们可使用纯 JavaScript 来调用丰富的原生 APIs。javascript

Electron用 web 页面做为它的 GUI,而不是绑定了 GUI 库的 JavaScript。它结合了 Chromium、Node.js 和用于调用操做系统本地功能的 APIs(如打开文件窗口、通知、图标等)。html

Electron-Quick-Start-00

如今已经有不少由 Electron 开发应用,好比 AtomInsomniaVisual Studio Code 等。查看更多使用 Electron 构建的项目能够访问 [Apps Built on Electron
](https://electron.atom.io/apps/)前端

安装

安装 electron 以前,须要安装 Node.js。若是没有安装,推荐使用 nvm 等 Node.js 版本管理工具进行安装/java

而后建议修改 electron 的源为国内源:node

$ export ELECTRON_MIRROR="https://npm.taobao.org/mirrors/electron/"

否则会出现以下错误:git

Error: connect ETIMEDOUT 54.231.50.42:443
    at Object.exports._errnoException (util.js:1016:11)
    at exports._exceptionWithHostPort (util.js:1039:20)
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1138:14)

安装 electron:github

$ npm install electron -g

进程

Electron 的进程分为主进程和渲染进程。web

主进程

在 electron 里面,运行 package.json 里面 main 脚本的进程成为主进程。主进程控制整个应用的生命周期,在主进程中能够建立 Web 形式的 GUI,并且整个 Node API 是内置其中。npm

渲染进程

每一个 electron 的页面都运行着本身的进程,称为渲染进程。json

主进程与渲染进程的联系及区别

主进程使用 BrowserWindow 实例建立页面。每一个 BrowserWindow 实例都在本身的渲染进程里运行页面。当一个 BrowserWindow 实例被销毁后,相应的渲染进程也会被终止。

主进程管理全部页面和与之对应的渲染进程。每一个渲染进程都是相互独立的,而且只关心他们本身的页面。

在 electron 中,页面不直接调用底层 APIs,而是经过主进程进行调用。因此若是你想在网页里使用 GUI 操做,其对应的渲染进程必须与主进程进行通信,请求主进程进行相关的 GUI 操做。

在 electron 中,主进程和渲染进程的通讯主要有如下几种方式:

  • ipcMain、ipcRender

  • Remote 模块

进程通讯将稍后详细介绍。

打造第一个 Electron 应用

如下全部代码能够在 https://github.com/nodejh/electron-quick-start 找到。

一个最简单的 electron 应用目录结构以下:

electron-demo/
├── package.json
├── main.js
└── index.html

package.json 与 Node.js 的彻底一致,因此咱们可使用 npm init 来生成。而后将 "main": "index.js" 修改成 "main": "main.js"。之因此命名为 main.js,主要是为了与主进程这个概念对应。

main.js

建立 main.js 文件并添加以下代码:

const electron = require('electron');

const {
  app, // 控制应用生命周期的模块
  BrowserWindow, // 建立原生浏览器窗口的模块
} = electron;

// 保持一个对于 window 对象的全局引用,若是不这样作,
// 当 JavaScript 对象被垃圾回收, window 会被自动地关闭
let mainWindow;

function createWindow() {
  // 建立浏览器窗口。
  mainWindow = new BrowserWindow({width: 800, height: 600});

  // 加载应用的 index.html。
  // 这里使用的是 file 协议,加载当前目录下的 index.html 文件。
  // 也可使用 http 协议,如 mainWindow.loadURL('http://nodejh.com')。
  mainWindow.loadURL(`file://${__dirname}/index.html`);

  // 启用开发工具。
  mainWindow.webContents.openDevTools();

  // 当 window 被关闭,这个事件会被触发。
  mainWindow.on('closed', () => {
    // 取消引用 window 对象,若是你的应用支持多窗口的话,
    // 一般会把多个 window 对象存放在一个数组里面,
    // 与此同时,你应该删除相应的元素。
    mainWindow = null;
  });
}

// Electron 会在初始化后并准备
// 建立浏览器窗口时,调用这个函数。
// 部分 API 在 ready 事件触发后才能使用。
app.on('ready', createWindow);

// 当所有窗口关闭时退出。
app.on('window-all-closed', () => {
  // 在 macOS 上,除非用户用 Cmd + Q 肯定地退出,
  // 不然绝大部分应用及其菜单栏会保持激活。
  if (process.platform !== 'darwin') {
    app.quit();
  }
});

app.on('activate', () => {
  // 在 macOS 上,当点击 dock 图标而且该应用没有打开的窗口时,
  // 绝大部分应用会从新建立一个窗口。
  if (mainWindow === null) {
    createWindow();
  }
});

关于 appBrowserWindow 对象和实例的更多用法可参考 electron 的文档:

index.html

而后编辑须要展现的 index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Hello World!</title>
    <style media="screen">
      .version {
        color: red;
      }
    </style>
  </head>
  <body>
    <h1>Hello World!</h1>
    We are using Node.js
    <span id="version-node" class="version"></span>
    and Electron
    <span id="version-electron" class="version"></span>
    <script type="text/javascript">
      console.log('process: ', process);
      var versionNode = process.version;
      var versionElectron = process.versions['electron'];
      document.getElementById('version-node').innerText = versionNode
      document.getElementById('version-electron').innerText = versionElectron
    </script>
  </body>
</html>

在这个例子中,咱们显示出了 electron 使用的 Node.js 版本和 electron 的版本。index.html 跟网页的 HTML 一摸同样,只是多了一些 electron 的全局对象。

运行

由于前面已经全局安装了 electron,因此咱们可使用 electron 命令来运行项目。在 electron-demo/ 目录里面运行下面的命令:

$ electron .

而后会弹出一个 electron 应用客户端,如图所示:

Electron-Quick-Start-01

由于在主进程中启用了开发模式 mainWindow.webContents.openDevTools(),因此默认启动开发者工具。

若是是局部安装的 electron,即 npm install --save electron,则能够运行下面的命令来启动应用:

$ ./node_modules/.bin/electron .

进行通讯

对于 electron 来讲,主进程和渲染进程直接的通讯是必不可少的。

前面提到过 electron 进程间的通讯的方式主要有两种,一种是用于发送消息的 ipcMainipcRenderer 模块,一种用于 RPC 的 remote 模块。

如今假设一个业务场景,用户在页面中输入文本消息,渲染进程将消息发送给主进程,主进程处理后将处理结果返回给页面。为了方便起见,主进程的处理就假设为翻转文本。固然,这个功能在前端彻底能够实现,这里只是为了演示进程通讯。

ipcMain 和 ipcRenderer

首先在渲染进程中添加一个输入框和一个按钮,并实现点击按钮获取输入框的内容。而后使用 ipcRenderer 发送消息。主进程接收到消息并处理以后,会返回处理结果。因此渲染进程中还须要接收主进程的消息。

修改 index.html,添加下面的代码:

<!-- 在 body 部分添加一个输入框和按钮 -->
<div>
  <input type="text" id="message" name="" value="">
  <br/>
  <button type="button" id="button" name="button">click me</button>
</div>

<script type="text/javascript">
  // ...

  // 添加下面的代码。
  // 引入 ipcRenderer 模块。
  var ipcRenderer = require('electron').ipcRenderer;
  document.getElementById('button').onclick = function () {
    var message = document.getElementById('message').value;
    // 使用 ipcRenderer.send 向主进程发送消息。
    ipcRenderer.send('asynchronous-message', message);
  }

  // 监听主进程返回的消息
  ipcRenderer.on('asynchronous-reply', function (event, arg) {
    alert(arg);
  });
</script>

接下来在主进程中接收渲染进程的消息,并进行处理(翻转字符串),而后将处理结果发送给主进程。修改 main.js 以下:

//...

// 监听渲染进程发送的消息
ipcMain.on('asynchronous-message', (event, arg) => {
  const reply = arg.split('').reverse().join('');
  console.log('reply: ', reply);
  // 发送消息到主进程
  event.sender.send('asynchronous-reply', reply);
});

而后从新运行项目。在页面的输入框内输入字符,点击按钮,就能弹出以下的弹出框,说明渲染进程与主进程通讯成功:

http://oh1ywjyqf.bkt.clouddn.com/Electron-Quick-Start-02.png

remote

remote 模块提供了一种在渲染进程(网页)和主进程之间进行进程间通信(IPC)的简便途径。

使用 remote 模块,咱们能够很方便地调用主进程对象的方法,而不须要发送消息。

index.html<script> 标签中添加以下代码:

// 引入 remote 模块
var remote = require('electron').remote;
// 获取主进程中的 BrowserWindow 对象
var BrowserWindow = remote.BrowserWindow;
// 建立一个渲染进程
var win = new BrowserWindow({ width: 200, height: 150 });
win.loadURL('http://nodejh.com');

而后使用 ctr + r 组合键刷新应用,就会看到建立出的一个新窗口。

打包

Electron 应用开发完成以后,还须要将其打包成对应平台的客户端。经常使用的打包工具备 electron-packagerasar

这里以 electron-packager 为例。首先全局安装 electron-packager:

$ npm install electron-packager -g

而后在项目中安装 electron:

$ npm install electron --save-dev

而后打包:

$ electron-packager . electron-demo

总结

本文首先对 electron 作了简单的介绍,而后讲解了 electron 进程的概念,其进程包括主进程和渲染进程。而后建立了一个简单的 electron 应用,并经过实现一个简单的应用场景,对 electron 进程间的通讯作了实践。整体来讲,使用 electron 建立桌面客户端的开发体验跟写 Node.js 和网页差很少。但本文对内置模块好比 app、ipcMain、ipcRender、remote 等的介绍比较粗浅,涉及到一些内置模块的使用,还须要继续查询 electron 的官方文档,只有实践越多,才能越熟悉。

https://github.com/nodejh/nodejh.github.io/issues/39

--