Electron – 创建跨平台的桌面客户的应用程序

Electron – 创建跨平台的桌面客户的应用程序
Electron 框架的前身是 Atom Shell,可以让你写使用 JavaScript,HTML 和 CSS 构建跨平台的桌面应用程序。它是基于io.js 和 Chromium 开源项目,并用于在 Atom 编辑器中。Electron 是开源的,由 GitHub 维护,有一个活跃的社区。最重要的是,Electron 应用服务构建和运行在 Mac,Windows 和 Linux。
Electron 结合了 Chromium、Node.js 和用于调用操作系统本地功能的 API(如打开文件窗口、通知、图标等)。
![title](https://leanote.com/api/file/getImage?fileId=58f4ce1aab64415134004063)

开发体验如何?
基于 Electron 的开发,就好像开发一个网页一样,而且能够无缝地 使用 Node。或者说:就好像构建一个 Node app,并通过 HTML 和 CSS 构建界面。另外,你只需为一个浏览器(最新的 Chrome)进行设计。

如何运用Electron开发桌面应用?

Electron是一个通过node服务搭建web的app。
Electron中的app模块主宰着这个应用的生命周期,创建可视window窗口需要等app模块确认准备就绪。
BrowserWindow模块 控制着可视窗口的创建,所有被创建出的窗口都是BrowserWindow模块的 new BrowserWindow(WINDOW_BOUNDS)方法来实例化的,通过实例的方法loadURL(HTML_URL)方法来加载要渲染的页面。这样一个简单的桌面应用便生成了。
简例如下:

app.on(‘ready’, () => {
let mainWindow = new BrowserWindow(win_para);
mainWindow.loadURL(config.mainUrl);
mainWindow.on(‘closed’, () => {
mainWindow = null;
app.quit()
});
mainWindow.on(‘ready-to-show’, () => {
mainWindow.show()
mainWindow.focus()
});
return mainWindow;
});

Electron 的进程:
Electron 有两种进程:主进程和渲染进程。有些模块会工作在其中一个进程上,而有些会在两个进程之上。主进程多地充当幕后角色,而渲染进程则是应用的每个窗口(window)。因为爱学习授课客户端的需求,所以目前的桌面应用暂时应用了一个主进程和一个渲染进程(后台进程,主要支持下载)
主进程:
主进程,通常通常是类似命名为main.js主文件所创建,该文件是每个 Electron 应用的入口。它控制了应用的生命周期(从打开到关闭)。它能调用原生元素和创建新的(多个)渲染进程,而且整个 Node API 是内置其中的。主进程中的IpcMain模块是与渲染进程通讯的主要手段
![title](https://leanote.com/api/file/getImage?fileId=58f4dac3ab64415134004173)
渲染进程:
渲染进程,可以是一个或多个创建出来的window模块,这些进程不被允许直接操控GUI,通常需要IpcRenderer模块与IpcMain模块进行通讯,也可以通过remote模块间接操控主进程,但是确实不提倡,也是不安全的。
![title](https://leanote.com/api/file/getImage?fileId=58f4daceab64414e1d004216)
简例:

/**
* 主进程 监听 自定义事件: 下载续传
*/
ipcMain.on(‘download-resume-hanlder’, (ipcResumeEvent, options) => {
if (_QUEUE.queueList[options].canResume()) {
_QUEUE.queueList[options].resume();
// 通讯事件通过sender.send(para)方法与渲染进程异步通讯
ipcResumeEvent.sender.send(‘download-has-resumed’, _QUEUE.queueList, _QUEUE.queueList.length);
} else {
IpcResumeEvent.sender.send(‘download-has-destroyed’);
}
});
/**
* 渲染进程 监听 自定义事件: 下载续传
*/
ipcRenderer.on(‘download-has-resumed’, (ipcResumeEvent, fileQueue, times) => {
//code to operate js
});
/**
* 渲染进程 发射 自定义事件: ‘download-has-paused’
*/
ipcRenderer.send(‘download-has-paused’, msg);

![title](https://leanote.com/api/file/getImage?fileId=58f4e25cab644151340041f4)

模块:
Electron 的 API 是根据它们的功能进行分组。例如:dialog 模块拥有所有原生 dialog 的 API,如打开文件、保存文件和弹窗。
授课客户端暂时用到的模块主要如下:
app, browserWinodw, ipcMain, ipcRender, remote, dialog, session, webContents, shell, fs, path。
app 模块是为了控制整个应用的生命周期设计的。
BrowserWindow 模块让你有创建一个浏览器窗口的权力。
ipcMain 模块是类 EventEmitter 的实例.当在主进程中使用它的时候,它控制着由渲染进程(web page)发送过来的异步或同步消息.从渲染进程发送过来的消息将触发事件。
ipcRenderer 模块是一个 EventEmitter 类的实例. 它提供了有限的方法,你可以从渲染进程向主进程发送同步或异步消息。 也可以收到主进程的响应。
remote 模块提供了一种在渲染进程(网页)和主进程之间进行进程间通讯(IPC)的简便途径。
dialog 模块提供了api来展示原生的系统对话框,例如打开文件框,alert框,所以web应用可以给用户带来跟系统应用相同的体验。
session 模块可以用来创建一个新的 Session 对象。主要应用于下载。
webContents 是一个 事件发出者。它负责渲染并控制网页,也是 BrowserWindow 对象的属性。
shell 模块提供了集成其他桌面客户端的关联功能。
fs 模块主要是文件读写,本地文件系统操作。
path 模块主要是文件在系统中的路径。

Electron使用一个 package.json 文件。该文件能定义哪个文件作为主进程,并因此让 Electron 知道从何启动你的应用。然后主进程能创建渲染进程,并能使用 IPC 让两者间进行消息传递。
![title](https://leanote.com/api/file/getImage?fileId=58f4e289ab644151340041f6)

以上是关于Elertron这个APP的简短介绍。下面是客户端的Two-Package Structure,及APP Package等方面的简介。

Two-Package Structure:

Two-Package Structure 是 pack 工具 electron-builder 给的约定,也是目前业界用的较多的方案。

![Two-Package Structure](https://leanote.com/api/file/getImage?fileId=58f4e9e7ab64415134004267)

为啥用 Two-Package Structure?

最大的好处是可以很好地分离开发依赖和生成环境依赖。开发依赖存 package.json ,生产依赖存 app/package.json ,这样在 pack 后交付给用户时就不会包含 webpack, mocha 等等的开发依赖了。

Electron 应用的打包

Electron 应用的打包 是应用了脚手架 electron-packager。首先将项目文件打包,然后应用electron-packager来打包electron应用.
可以用命令打包一个供windows使用的app: electron-packager ./app aixuexi –platform=win32 –arch=x64 –out=./dist –asar true –overwrite “,
也可以自行添加文件配置electron的打包参数 如:

building: {
‘app-version’: appPackage.version,
arch: [‘x64’, ‘ia32’], ia32, x64, armv7l, all
asar: false,
dir: path.join(__dirname, ‘/app’),
icon: path.join(__dirname, ‘app/icons/icon’),
ignore: /src|main.ejs|icons/,
out: path.join(__dirname, ‘/app/dist’),
overwrite: true,
platform: process.env.PLATFORM_TARGET || ‘all’,
name: appPackage.product
}

待续…