只需五分钟,就会Electron
。html
Electron是由Github开发,用HTML
,CSS
和JavaScript
来构建跨平台桌面应用程序的一个开源库。 Electron经过将Chromium和 Node.js 合并到同一个运行时环境中,打包出能够运行在Mac
,Windows
和Linux
系统下的应用。前端
Chromium
的 渲染库 而不是 Chromium是由Google主导开发的网页浏览器,说明白点:node
Chromium是Chrome浏览器背后的引擎。react
若是把 浏览器 和 Node.js 联系在一块儿,通常想到的一个web服务,TCP以及其衍生协议充当了页面
与服务器
通讯的桥梁。linux
浏览器能够调用原生功能,很容易让人联想到Hybrid,web经过自定义的桥接协议
与Native通讯,Native拦截请求从而得知web须要调用的功能。git
在一个Electron桌面应用分红两个进程:github
主进程负责管理原生操做,例如: 文件读写,图形处理,程序开关等,同时还管理渲染进程以及应用的生命周期。web
渲染进程经过 Chromium 绘制前端界面,用户能够在页面上触发事件。shell
那么,Node.js 如何与Chromium通讯?npm
答案是 IPC——进程间通讯。
Electron IPC提供了基于事件的API,在渲染进程和后台进程中均可以向对方发送事件,也能够在事件处理函数中经过发送的新的事件回复对方:
EventEmitter
实例向对方发送事件npm install electron --save-dev --save-exact
复制代码
若是下的慢,能够尝试淘宝镜像。
.
└── app
├── main.js
├── index.js
├── index.html
├── package.json
复制代码
main.js 是主进程执行文件, index.html 和 index.js 是渲染进程的视图,和平时写的网页同样。
须要在package.json写明App名称等信息,同时 须要指定入口文件(即main.js
),举个例子:
{
"name": "app",
"productName": "app",
"version": "0.0.1",
"main": "./app/index.js"
}
复制代码
更详细的范例能够参照官方示例:electron-quick-start
主进程服务加上npm scripts
:
"dev:electron-main": "cross-env NODE_ENV='development' electron -r babel-register ./",
复制代码
启动主进程:
npm run dev:electron-main
复制代码
electron主进程文件修改以后须要重启应用才能生效,每次手动重启不方便,推荐使用鄙人抖机灵撸的一个包:
食用方法,在主进程文件中插入下面代码片断:
if (process.env.NODE_ENV === 'development') {
require('electron-watch')(
__dirname,
'dev:electron-main', // means: npm run dev:electron-main
path.join(__dirname, './'),
);
}
复制代码
** PS: 该库Windows上有bug,正确的食用发放是只按一次Ctrl+S
,同时按几回会重启多个应用。 **
electron提供了丰富的API让你调用原生的功能,参见electron文档。
可是过一下下面这几个模块,就能够快速撸出一个Electron App。
一个桌面应用对象,提供API控制应用,同时能够监控应用程序的事件生命周期。
例如在最后一个窗口被关闭时退出应用:
const {app} = require('electron');
app.on('window-all-closed', () => {
app.quit();
});
复制代码
能够监控的生命周期事件:
will-finish-launching
:当应用程序完成基础的启动的时候被触发ready
: 当 Electron`: 完成初始化时被触发window-all-closed
:当全部的窗口都被关闭时触发before-quit
:在应用程序开始关闭窗口以前触发will-quit
: 当全部窗口都已关闭而且应用程序将退出时发出quit
:在应用程序退出时发出一个浏览器窗口
建立一个浏览器窗口:
import { app, BrowserWindow } from 'electron';
app.on('ready', () => {
const win = new BrowserWindow({width: 800, height: 600});
// 加载远程URL
win.loadURL('https://www.coolecho.net');
// 或加载本地HTML文件
win.loadURL(`file://${__dirname}/app/index.html`);
});
复制代码
父子窗口:
const {BrowserWindow} = require('electron');
const top = new BrowserWindow();
/** * 加上model属性,子窗口为模态窗口,父窗口被禁用 */
const child = new BrowserWindow({parent: top})
child.show()
top.show()
复制代码
child
窗口将老是显示在 top
窗口的顶部,长得像这个样子:
ipcMain
是EventEmitter
类的一个实例。 当在主进程中使用时,ipcRender
处理从 渲染器进程(网页) 发送出来的异步和同步信息。 从渲染器进程发送的消息将被发送到该模块。
ipcRenderer
也是一个 EventEmitter
的实例。 你能够使用它提供的一些方法从渲染进程 (web 页面) 发送同步或异步的消息到主进程。 也能够接收主进程回复的消息。
下面是在渲染和主进程之间发送和处理消息的一个例子:
// 在主进程中
const {ipcMain} = require('electron');
// 异步
ipcMain.on('asynchronous-message', (event, arg) => {
console.log(arg); // prints "ping"
event.sender.send('asynchronous-reply', 'pong');
});
// 同步
ipcMain.on('synchronous-message', (event, arg) => {
console.log(arg) // prints "ping"
event.returnValue = 'pong'
});
复制代码
//在渲染器进程 (网页) 中
const {ipcRenderer} = require('electron');
// 同步请求
console.log(ipcRenderer.sendSync('synchronous-message', 'ping'));
// 异步发送请求
ipcRenderer.on('asynchronous-reply', (event, arg) => {
console.log(arg) // prints "pong"
});
// 异步接收返回
ipcRenderer.send('asynchronous-message', 'ping');
复制代码
你能够经过ipcMain
和ipcRenderer
模块,在渲染页面中调用原生功能处理一些事物,固然electron
作到的远不止这些,它还提供了remote模块。使用 remote
模块, 你能够调用 主进程对象 的方法, 而没必要显式发送进程间消息。
建立原生应用菜单和上下文菜单。
import { Menu } from 'electron';
const menuTemplete = [{
label: 'File',
submenu: [{
label: 'New Note',
accelerator: 'CmdOrCtrl+N',
enabled: false,
// role: 'new file',
click: () => mainWindow.webContents.send('new-file', 1),
}, {
label: 'New Project',
accelerator: 'Shift+CmdOrCtrl+N',
enabled: false,
// role: 'new project',
click: () => mainWindow.webContents.send('new-project'),
}, {
type: 'separator',
}, {
label: 'Save',
accelerator: 'CmdOrCtrl+S',
role: 'save',
enabled: false,
click: () => mainWindow.webContents.send('save-content'),
}],
}];
const menu = Menu.buildFromTemplate(menuTemplete);
Menu.setApplicationMenu(menu);
复制代码
效果:
还能够建立Context菜单:
const menu = new Menu();
menu.append(new MenuItem({
label: 'Rename',
click: () => mainWindow.webContents.send('rename-project'),
}));
menu.append(new MenuItem({
label: 'Delete',
click: () => mainWindow.webContents.send('delete-project'),
}));
menu.append(new MenuItem({
type: 'separator',
}));
menu.append(new MenuItem({
label: 'New Notebook',
click: () => mainWindow.webContents.send('new-project'),
}));
// 项目右键菜单
ipcMain.on('show-context-menu-project-item', (event) => {
const win = BrowserWindow.fromWebContents(event.sender);
menu.popup(win);
});
复制代码
效果:
Electron
提供了不少属性来定制一个菜单项,例如上面例子中的label
,click
,role
等等:
click
: 点击菜单项的回调方法role
: Electron
定制的内置事件,有click
的时候,此项将被忽略type
: 能够是 normal
、separator
、submenu
、checkbox
或 radio
。label
: 菜单名称,当设置role时默认为roleaccelerator
: 定义快捷键icon
sublabel
enabled
: 若是为 false,该菜单项将会置灰且不可点击visible
: 控制菜单项是否可见checked
: 控制菜单项是否选中,type
为chckbox
或radio
时有效submenu
: 定义子菜单项id
: 能够经过它来引用该菜单项position
: 容许对给定菜单中的特定位置进行细粒度定义(没试过)基本上知道上诉三个模块,就能够开发一个Electron APP了,但Electron的模块远远不止这些,它还囊括网络、电源、通知、进程、菜单、本地化、协议、会话、Shell等等模块,详细的介绍参阅Electron文档。
应用开发完了,接下来得打包了。
有三种种打包方式:
1,3两种方式有点繁琐,这里介绍几个经常使用的打包工具:
若是想在APP STORE上架应用,,这需使用XCode填写证书和开发者信息,手动打包。
我用的是electron-packer
,打包起来十分方便,看看npm script
:
"packager:mac": "electron-packager ./lib Yosoro --overwrite --platform=darwin --arch=x64 --out=out --icon=assets/icons/osx/app.icns",
"packager:win": "electron-packager ./lib Yosoro --overwrite --platform=win32 --arch=ia32 --out=out --icon=assets/icons/win/app.ico",
"packager:linux": "electron-packager ./lib Yosoro --overwrite --platform=linux --arch=x64 --out=out",
复制代码
--icon
参数是用来指定应用的logo的,macOS
下是.icns
格式, Windows
下是.ico
格式。
为啥Linux
的没有这个命令行参数呢?
由于Linux
的Logo须要在初始化Electron应用的时候指定,格式为PNG
和JPEG
,建议使用PNG
:
const options = {
title: 'Yosoro',
width: 1180,
height: 786,
};
if (process.platform === 'linux') { // 加上logo
options.icon = path.join(__dirname, './resource/app.png');
}
mainWindow = new BrowserWindow(options);
复制代码
options.icon
这个属性在macOS
和Windows
下是无效的。
最后,你觉得直接npm run
这三条命令就完事了吗?
electron-packager
只在对的地方干对的事,例如,在macOS上只打macOS上运行的包,Windows上只打Windows上运行的包,从不会干多余的打包工做。好比在macOS
下会直接打成一个APP
包:
若是你想分别打三端的包,须要分别在macOS
,Windows
,Linux
这三个环境下打包。
关于Electron
还有很是强大的功能,例如热更新等等,本文只是菜鸡随手笔记,有错误的地方欢迎指正。
最后,关于Electron结合react的实例 戳这里,求star。