Electron 介紹
作為一名熱衷于新技術(shù)的前端開發(fā)工程師胚委,如果你一直期望著打造一款桌面應(yīng)用,又不希望付出太多的精力花費(fèi)在 C++叉信、.NET 等技術(shù)上亩冬,那么使用 Electron 這種低成本的技術(shù)來開發(fā)跨平臺(tái)的桌面應(yīng)用對(duì)我們來說性價(jià)比是非常高的,從而快速地點(diǎn)亮桌面應(yīng)用開發(fā)的技能點(diǎn)硼身。
Electron 是一個(gè)基于 V8 引擎和 Node.js 的開發(fā)框架硅急,允許用 JavaScript 開發(fā)跨平臺(tái)(Windows、Mac OS X 和 Linux)桌面應(yīng)用佳遂。用 Electron 開發(fā)的應(yīng)用有很多营袜,如 Visual Studio Code、Atom丑罪、支付寶小程序 IDE(螞蟻開發(fā)者工具)等荚板。
整體架構(gòu)概覽
Electron 主要包含兩類進(jìn)程,主進(jìn)程(Main Process)和渲染進(jìn)程(Renderer Process)吩屹。當(dāng)我們在啟動(dòng)一個(gè) App 時(shí)跪另,那么會(huì)先啟動(dòng)主進(jìn)程,主進(jìn)程會(huì)啟動(dòng)應(yīng)用并創(chuàng)建 native UI煤搜,隨后會(huì)在 native UI 上啟動(dòng)一個(gè)或多個(gè)的 browser window 即 web pages免绿,每一個(gè) BrowserWindow 都是一個(gè)渲染進(jìn)程 身害。在 native UI 上的不同的 browser windows 它們是獨(dú)立的沙箱環(huán)境橘茉,不同的進(jìn)程之間是互相隔離的,Electron 提供了幾種進(jìn)程之間通信的方式相恃,比如 IPC(inter-process communication)和 RPC(remote-process communication)厌衙。
主進(jìn)程(Main Process)和渲染進(jìn)程(Renderer Process)
Main Process
Electron 運(yùn)行 package.json 的 main 腳本(程序的入口)的進(jìn)程被稱為主進(jìn)程距淫,一個(gè)應(yīng)用只有一個(gè)主進(jìn)程绞绒,主進(jìn)程可以:
- 主進(jìn)程包含了 Chromium 和 Node 的運(yùn)行時(shí)環(huán)境婶希;
- 主進(jìn)程可以通過實(shí)例化 BrowserWindow 展示 Web 頁面,每一個(gè) Web 頁面都會(huì)運(yùn)行在它自己的 渲染進(jìn)程 中蓬衡;
- 主進(jìn)程可以訪問原生的 API(注冊快捷鍵喻杈、創(chuàng)建菜單欄等)彤枢,如果渲染進(jìn)程需要訪問原生 API,那么需要和主進(jìn)程進(jìn)行通信筒饰,請求主進(jìn)程來進(jìn)行相關(guān)的調(diào)用缴啡,再返回給渲染進(jìn)程;
- 主進(jìn)程可以管理所有的 Web 頁面和其對(duì)應(yīng)的渲染進(jìn)程瓷们。
Renderer Process
渲染進(jìn)程主要是用來渲染 Web 頁面业栅,并且兼容傳統(tǒng)的 Web 頁面,支持所有的 DOM API谬晕、Node API碘裕。除此之外,渲染進(jìn)程還可以通過和主進(jìn)程通信來訪問原生的 API攒钳。
常用模塊的介紹
Electron 提供的模塊也是按照主進(jìn)程和渲染進(jìn)程來進(jìn)行劃分帮孔,不能的模塊只能在其對(duì)應(yīng)的進(jìn)程使用,下面介紹幾種常用到的模塊不撑。
app 模塊
app 模塊在主進(jìn)程中使用文兢。用來控制整個(gè)應(yīng)用程序的事件生命周期,常見的幾種監(jiān)聽事件有 ready焕檬、before-quit姆坚、will-quit。
const {app} = require('electron')
app.on('ready', ()=>{
console.log('當(dāng) Electron 完成初始化時(shí)被觸發(fā)')
})
app.on('before-quit', (e)=>{
// 可以調(diào)用 e.preventDefault() 來阻止默認(rèn)的行為(即關(guān)閉應(yīng)用程序)
console.log('在應(yīng)用程序開始關(guān)閉窗口之前觸發(fā)')
})
app.on('will-quit', (e)=>{
// 可以調(diào)用 e.preventDefault() 來阻止默認(rèn)的行為(即關(guān)閉應(yīng)用程序)
console.log('在所有的 Web 窗口關(guān)閉实愚,應(yīng)用程序即將退出時(shí)觸發(fā)')
})
BrowserWindow 模塊
BrowserWindow 模塊在主進(jìn)程中使用旷偿。用來創(chuàng)建管理瀏覽器窗口,并且可以控制窗口的大小爆侣、邊框萍程、標(biāo)題欄樣式等。
const {app} = require('electron')
const isDev = require('electron-is-dev')
const path = require('path')
let win
const createWindow = () => {
win = new BrowserWindow({
show: false, // 先不顯示 Web 頁面兔仰,等加載后在顯示
webPreferences: {
nodeIntegration: true // Web 集成 node 環(huán)境
},
titleBarStyle: 'hiddenInset' //設(shè)置標(biāo)題欄樣式茫负,隱藏標(biāo)題欄, 顯示小的控制按鈕在窗口邊緣
})
win.maximize() //打開后自動(dòng)最大化窗口
win.loadURL(isDev
? 'http://localhost:3000/'
: `file://${path.join(__dirname, './index.html')}`)
if (isDev) {
win.webContents.openDevTools();
}
win.once('ready-to-show', () => {
win.show()
})
}
app.on('ready', createWindow) // 監(jiān)聽 app 啟動(dòng)后,創(chuàng)建 BrowserWindow 打開 Web 頁面
關(guān)于 BrowserWindow 的更多配置項(xiàng)參考:
https://www.electronjs.org/docs/api/browser-window#new-browserwindowoptions
ipcMain乎赴、webContents 模塊
ipcMain 模塊在主進(jìn)程中使用忍法。用來處理從渲染進(jìn)程(Web 頁面)發(fā)送出來的異步和同步信息,處理完后榕吼,也可以同步或異步將數(shù)據(jù)返回給渲染進(jìn)程饿序。
const {ipcMain} = require('electron')
// 監(jiān)聽由渲染進(jìn)程發(fā)送過來的事件,事件名稱是'renderer-process-message-listener'羹蚣,發(fā)送的數(shù)據(jù)是 data
ipcMain.on('renderer-process-message-listener', (event, data) => {
const backData = 'data'
event.returnValue = backData // 回復(fù)同步信息給渲染進(jìn)程
event.reply(backData) // 回復(fù)異步信息返回給發(fā)送過來的這個(gè)渲染進(jìn)程
event.sender.send(backData) // 回復(fù)異步信息給主窗口這個(gè)渲染進(jìn)程
})
webContents 模塊也是用于主進(jìn)程中原探。ipcMain 主要是用來處理由渲染進(jìn)程發(fā)送過來的事件,而 webContents 則是用來由主進(jìn)程主動(dòng)往渲染進(jìn)程中發(fā)送事件:
win = new BrowserWindow()
win.webContents.send('event-name', {data:'data'}) // 在主進(jìn)程中使用,調(diào)用 browserWindow 的 send 方法進(jìn)行發(fā)送事件
ipcRenderer 模塊
在渲染進(jìn)程中咽弦,主要用到的就是 ipcRenderer 模塊徒蟆,用于在渲染進(jìn)程(Web 頁面)中發(fā)送同步或異步消息到主線程,也可以接收由主進(jìn)程回復(fù)的消息:
const { ipcRenderer } = require('electron')
// 在渲染進(jìn)程中主動(dòng)往主進(jìn)程中發(fā)送消息 ipcRenderer.sendSync 同步發(fā)送型型,ipcRenderer.send 異步發(fā)送
const backData = ipcRenderer.sendSync('synchronous-msg', {data:'data'})
ipcRenderer.send('asynchronous-msg', {data:'data'})
ipcRenderer.on('main-process-msg-listener', (event, data) => {
})
腳手架的搭建
下載腳手架
1. 下載:
git clone https://github.com/Aceysx/electron-startup.git
2. 安裝項(xiàng)目依賴:(在項(xiàng)目根目錄下)
npm install
3. 啟動(dòng):(在項(xiàng)目根目錄下)
electron app/main //啟動(dòng) app
npm start // 啟動(dòng) web
Web 頁面啟動(dòng)成功后段审,刷新 App 窗口(Ctrl/cmd+r)加載 Web 頁面,即可以看到下面的頁面:
腳手架的介紹
本 Chat 主要是為了介紹 Electron闹蒜,所以為了更加方便輕松地創(chuàng)建用戶交互界面寺枉、設(shè)計(jì)簡潔的數(shù)據(jù)狀態(tài),腳手架集成了 React绷落、Redux 和 Ant Design UI 幫助快速開發(fā)型凳。
如果讀者對(duì) React 不熟悉,也可以使用相應(yīng)的庫替換嘱函,或者直接使用 HTML/CSS/JavaScript甘畅。后續(xù)講解中涉及的 React、Redux 的相關(guān)內(nèi)容時(shí)也會(huì)做相應(yīng)的的說明往弓。
啟動(dòng)疏唾、調(diào)試
在啟動(dòng)成功后,可以看到帶有調(diào)試控制臺(tái)的 App 頁面函似,是不是很熟悉槐脏,和我們平時(shí)開發(fā)調(diào)試 Web 頁面一樣:
來看看腳手架都做了什么。
目錄結(jié)構(gòu)
electron-startup
-- app
---- main.js
-- public
---- index.html
-- src
---- ui
---- index.js
-- package.json