做者:鍾離,酷家樂PC客戶端負責人
原文地址:https://webfe.kujiale.com/electron-ku-jia-le-ke-hu-duan-kai-fa-shi-jian-fen-xiang-ru-keng-zhi-nan/
酷家樂客戶端:下載地址 https://www.kujiale.com/activity/136
文章背景:在酷家樂客戶端在V12改版成功後,咱們積累了許多的寶貴的經驗和最佳實踐。前端社區裏關於Electron知識相對較少,所以但願將這些內容以系列文章的形式分享出來。
系列文章:javascript
Electron所使用的技術棧(JavaScript、NodeJs、HTML、CSS)和web前端工程師完美契合。因而,愈來愈多的前端工程師,用Electron來開發桌面客戶端的開發,我也是其中的一員。css
雖然Electron技術棧對前端工程師比較友好,可是概念較多,和web前端開發仍是有很大差異的,寫個入坑指南但願能幫助讀者快速上手Electron。html
首先拋出一個問題,web應用是桌面客戶端嗎?顯然不是。那麼,問題來了,什麼樣的軟件纔是桌面客戶端呢?咱們既然要從web前端轉到客戶端開發,那麼就須要瞭解客戶端,就像咱們當初瞭解web應用同樣。前端
回到剛剛那個問題,桌面客戶端有兩個重要的特色:java
web應用有本身的GUI,必須在瀏覽器中執行,所以不是桌面客戶端。linux
瀏覽器能直接運行在操做系統上,並且有本身的GUI,所以瀏覽器是桌面客戶端。git
在剛剛接觸Electorn的時候,文檔看的我是眼花繚亂。在某個加班的深夜,我不由對天長嘆:這個東西到底能幹啥?github
這東西能幹啥?在經歷了Electron的反覆摩擦以後,我總結了Electron的幾個關鍵能力:web
NodeJs所有能力,與操做系統交互ajax
Electron提供的基礎模塊,主要與操做系統交互
Chromium提供的能力,主要提供GUI圖形界面
若是用戶安裝了咱們的桌面客戶端,那麼咱們的軟件在用戶電腦上運行時,就有了很是大的權利,這是把雙刃劍。
用戶選擇了咱們的軟件,咱們也要對用戶的電腦負責。能力越大,責任也就越大:
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,源代碼地址 https://github.com/littlecold233/electron-demo,例子有如下特色:
forceQuit
這個變量來控制。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