只需五分鐘,就會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。