做者:鍾離,酷家樂PC客戶端負責人javascript
原文地址:webfe.kujiale.com/electron-ku…css
酷家樂客戶端:下載地址 www.kujiale.com/activity/13…html
文章背景:在酷家樂客戶端在V12改版成功後,咱們積累了許多的寶貴的經驗和最佳實踐。前端社區裏關於Electron知識相對較少,所以但願將這些內容以系列文章的形式分享出來。前端
系列文章:java
Electron所使用的技術棧(JavaScript、NodeJs、HTML、CSS)和web前端工程師完美契合。因而,愈來愈多的前端工程師,用Electron來開發桌面客戶端的開發,我也是其中的一員。linux
雖然Electron技術棧對前端工程師比較友好,可是概念較多,和web前端開發仍是有很大差異的,寫個入坑指南但願能幫助讀者快速上手Electron。git
首先拋出一個問題,web應用是桌面客戶端嗎?顯然不是。那麼,問題來了,什麼樣的軟件纔是桌面客戶端呢?咱們既然要從web前端轉到客戶端開發,那麼就須要瞭解客戶端,就像咱們當初瞭解web應用同樣。github
回到剛剛那個問題,桌面客戶端有兩個重要的特色:web
web應用有本身的GUI,必須在瀏覽器中執行,所以不是桌面客戶端。ajax
瀏覽器能直接運行在操做系統上,並且有本身的GUI,所以瀏覽器是桌面客戶端。
在剛剛接觸Electorn的時候,文檔看的我是眼花繚亂。在某個加班的深夜,我不由對天長嘆:這個東西到底能幹啥?
這東西能幹啥?在經歷了Electron的反覆摩擦以後,我總結了Electron的幾個關鍵能力:
若是用戶安裝了咱們的桌面客戶端,那麼咱們的軟件在用戶電腦上運行時,就有了很是大的權利,這是把雙刃劍。
用戶選擇了咱們的軟件,咱們也要對用戶的電腦負責。能力越大,責任也就越大:
1.注意內存的佔用,特別是chromium,簡直是內存怪獸。能夠經過os來獲取用戶電腦的配置,而後根據電腦的配置和可用資源,來制定合理的策略。
一旦被貼上【流氓軟件】、【很差用】的標籤,就很難再改變用戶的印象了。
主進程:從整個應用啓動到結束,該進程一直存在。主進程只有一個。
渲染進程:主進程可用建立/銷燬渲染進程,所以渲染進程的生命週期是不固定的。渲染進程能夠有多個。
在Electron的API文檔中,會在文檔頂部標識該模塊在哪一個進程可用,例如:ipcRenderer
主進程 | 渲染進程 |
---|---|
控制app的生命週期,爲app註冊關鍵事件 | 解析HTML,渲染窗口內容 |
阻止一些默認行爲,例如webContents的跳轉、download事件的默認行爲等等(在渲染進程沒法作到) | 處理窗口的交互邏輯 |
建立BrowserWindow,也就是渲染進程。合理設置窗口的參數,控制窗口的生命週期(例如什麼時候銷燬窗口),決定BrowserWindow加載何處的HTML | 與主進程通訊,實現高級交互 |
咱們回顧一下剛剛講到的執行流程,其中有一個有趣的點,就是Electron的窗口會加載一個HTML來渲染窗口的內容。
HTML,以及HTML加載的css、js文件,統稱爲前端資源
若是不加載HTML的,客戶端還能用嗎?不妨來試試
// main process
const win1 = new BrowserWindow();
const win2 = new BrowserWindow();
複製代碼
上述代碼在主進程中執行,建立了兩個窗口,窗口並沒加載HTML文件。可是窗口倒是真實存在的,帶有系統標準的控制欄,可拖動,是貨真價實的系統窗口!
咱們能夠發現,前端資源和窗口是分離的。由主進程建立的的窗口(BrowserWindow),既是一個系統原生窗口,同時也是一個加載&渲染前端資源的容器
窗口一般會經過file協議和http(s)協議來加載前端資源,接下來咱們看看這兩種方式的區別。
在Electron的官方入門例子中,就是經過file協議來加載HTML的
經過file協議加載HTML,不管有沒有網絡,均可以加載到HTML文件,這是file協議核心優點。缺點也比較明顯:
經過http協議加載HTML,優勢是能夠隨時經過web頁面的部署,更新渲染進程的資源,而且在https協議下,你能夠在頁面中使用前端熟悉的ajax請求來獲取數據。
固然,缺點也比較明顯:
方便讀者更好理解上文的內容,寫了一個小demo,源代碼地址 github.com/littlecold2…,例子有如下特色:
建立主窗口,阻止關閉主窗口關閉的默認事件,不銷燬窗口。(大部分客戶端的主窗口,關閉主窗口的時候,其實是隱藏了該窗口,例如QQ、微信)
應用退出時,會嘗試關閉全部窗口,再退出應用。若是主窗口的關閉行爲默認事件被阻止,那麼會致使主窗口沒法關閉,整個應用沒法退出。所以使用forceQuit
這個變量來控制。
使用http或者file協議加載窗口前端資源(例子中,默認加載的是微信)
const { app, BrowserWindow } = require('electron')
async function main () {
await app.whenReady();
let forceQuit = false;
const majorWindow = new BrowserWindow({
title: '主窗口',
width: 1000,
height: 750,
minWidth: 1000,
minHeight: 750,
backgroundColor: '#f2f2f2',
}); // 主窗口
// 阻止標題更新
majorWindow.on('page-title-updated', (e) => {
e.preventDefault();
});
majorWindow.on('close', (e) => {
// 用戶但願退出的時候,不做處理,默認會銷燬這個窗口
if (forceQuit) return;
e.preventDefault();
// macOS全屏的處理
if (majorWindow.isFullScreen()) {
majorWindow.once('leave-full-screen', () => {
majorWindow.hide();
});
majorWindow.setFullScreen(false);
} else {
majorWindow.hide(); // 隱藏窗口
}
});
// 點擊dock打開主窗口
app.on('activate', () => {
majorWindow.show();
});
// 用戶使用cmd + Q、代碼中調用app.quit等狀況
// 此時用戶但願可以退出應用,所以將forceQuit改成true
app.on('before-quit', () => {
forceQuit = true;
});
app.dock.setIcon('./img/icon.png'); // 在app打包後,這一句代碼實際上是不須要的
majorWindow.loadURL('https://wx.qq.com'); // http協議加載前端資源,隨便加載一個微信試試
// majorWindow.loadURL('file://index.html'); // file協議加載前端資源
}
main();
複製代碼
在本地跑一下這個例子
歡迎你們在評論區討論,技術交流 & 內推 -> zhongli@qunhemail.com