开发基础

Electron 环境搭建与开发基础

It's just a global trend in every aspect of our economy, to externalize the costs. Saving dev time at the expense of resources is a tried and true strategy that has worked throughout history and will continue to work into the future.

Electron 可以让你使用纯 JavaScript 调用丰富的原生 APIs 来创造桌面应用。你可以把它看作是专注于桌面应用而不是 Web 服务器的 io.js 的一个变体。这不意味着 Electron 是绑定了 GUI 库的 JavaScript。相反,Electron 使用 Web 页面作为它的 GUI,所以你能把它看作成一个被 JavaScript 控制的,精简版的 Chromium 浏览器。

The desktop app is a host for some number of guest pages. The guest pages are like browser tabs pointed at slack.com, which we call the webapp. Although the webapp is on its own quest for modernity, this post is about the Electron container around it.

Support for notifications across all platforms — even Windows 7 Support for spell-check and language detection App, tray, taskbar, and context menus Support for deep-linking, launch on login, taskbar and dock badging Installers for all platforms — mainly Windows

Process(进程)

主进程

在 Electron 里,运行 package.jsonmain 脚本的进程被称为主进程。在主进程运行的脚本可以以创建 web 页面的形式展示 GUI。

渲染进程

由于 Electron 使用 Chromium 来展示页面,所以 Chromium 的多进程结构也被充分利用。每个 Electron 的页面都在运行着自己的进程,这样的进程我们称之为渲染进程。在一般浏览器中,网页通常会在沙盒环境下运行,并且不允许访问原生资源。然而,Electron 用户拥有在网页中调用 io.js 的 APIs 的能力,可以与底层操作系统直接交互。

主进程与渲染进程的区别

主进程使用 BroswerWindow 实例创建网页。每个 BroswerWindow 实例都在自己的渲染进程里运行着一个网页。当一个 BroswerWindow 实例被销毁后,相应的渲染进程也会被终止。主进程管理所有页面和与之对应的渲染进程。每个渲染进程都是相互独立的,并且只关心他们自己的网页。由于在网页里管理原生 GUI 资源是非常危险而且容易造成资源泄露,所以在网页面调用 GUI 相关的 APIs 是不被允许的。如果你想在网页里使用 GUI 操作,其对应的渲染进程必须与主进程进行通讯,请求主进程进行相关的 GUI 操作。在 Electron,我们提供用于在主进程与渲染进程之间通讯的 ipc 模块。并且也有一个远程进程调用风格的通讯模块 remote

Reference

Tutorials & Docs

Boilerplate

Practice

Quick Start

Installation

  • electron-prebuild

npm install -g electron-prebuilt

如果你已经用 npm 全局安装了 electron-prebuilt,你只需要按照如下方式直接运行你的应用:

electron .

如果你是局部安装,那运行:

./node_modules/.bin/electron .
  • 手工下载 Electron 二进制文件

如果你手工下载了 Electron 的二进制文件,你也可以直接使用其中的二进制文件直接运行你的应用。

(1)Windows

$ .\electron\electron.exe your-app\

(2)Linux

$ ./electron/electron your-app/

(3)OS X

$ ./Electron.app/Contents/MacOS/Electron your-app/

Electron.app 里面是 Electron 发布包,你可以在这里下载到。

Webpack

DevTools

```npm install --save-dev devtron require('devtron').install()

## HelloWorld
大体上,一个 Electron 应用的目录结构如下:

your-app/ ├── package.json //通用的node项目的声明文件

├── main.js //主进程渲染文件 ├── renderer.js //渲染进程文件 └── index.html //主入口文件

`package.json`的格式和 Node 的完全一致,并且那个被 `main` 字段声明的脚本文件是你的应用的启动脚本,它运行在主进程上。你应用里的 `package.json` 看起来应该像:

{ "name" : "your-app", "version" : "0.1.0", "main" : "main.js" }

**注意**:如果 `main` 字段没有在 `package.json` 声明,Electron 会优先加载 `index.js`。
### 主进程
`main.js` 应该用于创建窗口和处理系统时间,一个典型的例子如下:
```js
/**
* Created by apple on 16/6/3.
*/
const electron = require('electron');
// 用于控制应用生命周期
const { app } = electron;
// 用于创建本地窗口
const { BrowserWindow } = electron;
//为Window对象创建一个全局的引用,否则可能被JavaScript的垃圾回收机制自动回收
let win;
/**
* @function 创建窗口
*/
function createWindow() {
// 创建类似于浏览器的窗口
win = new BrowserWindow({ width: 800, height: 600 });
// 加载应用入口文件,本文件为测试文件,因此加载的是测试
win.loadURL(`file://${__dirname}/dist/app.html`);
// 启动调试工具,如果是开发环境下则不需要开启
win.webContents.openDevTools();
// 设置窗口关闭事件
win.on('closed', () => {
//因为上面是设置了一个全局引用,因此这里需要对该对象解除引用
//如果你的应用支持打开多窗口,可以把所有的引用存入一个数组中,然后在这里动态删除
win = null;
});
}
// 在基本环境准备好之后的回调
app.on('ready', createWindow);
// 所有窗口都关闭之后的回调
app.on('window-all-closed', () => {
//在OSX中经常是用户虽然关闭了主窗口,但是仍然希望使用Menu Bar,因此这里不进行强行关闭
// 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();
}
});
// 应用被重新激活之后的回调
app.on('activate', () => {
// 在Dock中的Menu Bar被点击之后重新激活应用
if (win === null) {
createWindow();
}
});

入口文件

最后,你想展示的 index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
<!-- All of the Node.js APIs are available in this renderer process. -->
We are using node
<script>
document.write(process.versions.node);</script
>, Chromium
<script>
document.write(process.versions.chrome);</script
>, and Electron
<script>
document.write(process.versions.electron);</script
>.
</body>
<script>
// You can also require other files to run in this process
require('./renderer.js');
</script>
</html>

渲染进程

实际上,在 Electron 项目中,关于 Hot-Reload 等等配置都和笔者在我的 Webpack 套装中提及的一系列配置方案。关于这方面的具体实践可以参考笔者ElectronOCR这个实战项目。