<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Jack Jiang

    我的最新工程MobileIMSDK:http://git.oschina.net/jackjiang/MobileIMSDK
    posts - 494, comments - 13, trackbacks - 0, articles - 1

    本文由蘑菇街前端技術團隊分享,原題“Electron 從零到一”,有修訂和改動。

    1、引言

    在上篇《快速了解新一代跨平臺桌面技術——Electron》,我們已經對Electron跨端框架有了基本的認識。

    本篇將帶你簡單上手Electron框架開發跨平臺桌面端,內容包括一個快速開始例子、跨進程通信原理、打包和分發、以及一些典型的技術踩坑等。希望能帶給你啟發。

    學習交流:

    本文已同步發布于:http://www.52im.net/thread-4039-1-1.html

    2、系列文章

    本文是系列文章中的第2篇,本系列總目錄如下:

    3、Electron簡介

    Electron 是一個賦力前端進行跨平臺開發的框架,讓開發人員使用 JavaScript、HTML 和 CSS 等前端技術構建跨平臺的桌面應用。

    Electron 通過將 Chromium(所有類Chrome的瀏覽器都是基于這個開源工程而來) 和 Node.js 合并到同一個運行時環境中(見下圖),并將其打包為 Mac,Windows 和 Linux 系統下的應用,而開發人員只需關注前端代碼的開發。

    ▲ 上圖引用自《快速了解新一代跨平臺桌面技術——Electron

    Chromium、Node.js、Native API這三者的作用分別是:

    • 1)Chromium :為Electron提供了強大的UI能力,可以不考慮傳統瀏覽器兼容性的情況下,利用強大的Web生態來開發界面;
    • 2)Node.js:讓Electron有了底層的操作能力(比如文件的讀寫,甚至是集成C++等等操作),并可以使用大量開源的npm包來完成開發需求。
    • 3)Native API:Native API讓Electron有了跨平臺和桌面端的原生能力(比如說它有統一的原生界面,窗口、托盤、消息通知這些)。

    Electron就是通過這三者的巧妙組合,讓我們開發跨平臺應用變的十分高效。

    本質上就是chromium(chrome開源版本)瀏覽器,有最新的東西都會在chromium測試,所以electron可以體驗最新的api,這也是好處之一。

    有關Electron的基本介紹等,這里就不再贅述,如果您還不曾了解,可以先閱讀本文的上篇。

    4、快速開始

    4.1 資料準備

    Electron 官方提供了一個名為electron-quick-start 的項目,可以 clone 下來當成模版使用,本文使用 create-react-app 來一步一步學習。

    其它重要的Electron開發資源:

    4.2 創建一個 react 項目

    # 安裝 create-react-app 命令,如果已將安裝請忽略

    npm install -g create-react-app

    # 創建 electron-react 項目

    create-react-app electron-react

    # 啟動項目

    cd electron-react && npm start

    4.3 配置 Electron 環境

    1)在 public 文件夾下新建 index.html,隨便寫點內容:

    ...

    <div>hello world</div>

    ...

    2)接下來創建 electron 主線程文件(public/main.js),建議寫在 public 路徑下面:

    const{app, BrowserWindow} = require('electron')

    // 創建全局變量并在下面引用,避免被GC

    let win

    function createWindow () {

        // 創建瀏覽器窗口并設置寬高

        win = newBrowserWindow({ width: 800, height: 600 })

        // 加載頁面

        win.loadFile('./index.html')

        // 打開開發者工具

        win.webContents.openDevTools()

        // 添加window關閉觸發事件

        win.on('closed', () => {

            win = null// 取消引用

        })

    }

    // 初始化后 調用函數

    app.on('ready', createWindow) 

    // 當全部窗口關閉時退出。

    app.on('window-all-closed', () => {

       // 在 macOS 上,除非用戶用 Cmd + Q 確定地退出,

       // 否則絕大部分應用及其菜單欄會保持激活。

       if(process.platform !== 'darwin') {

            app.quit()

       }

    })

    app.on('activate', () => {

    // 在macOS上,當單擊dock圖標并且沒有其他窗口打開時,

    // 通常在應用程序中重新創建一個窗口。

        if(win === null) {

          createWindow()

        }

    })

    3)接著再修改 package.json 中的 main 字段對應的路徑, 并添加 start 命令:

    {

        ...

        "main": "main.js",

        "scripts": "electron ."

    }

    4)執行 npm start,就會彈出如下運行界面:

    以上就是我簡單寫的一個頁面,大家也可以寫一寫自己感興趣的東西。

    真如上面演示的這樣,一個簡單的Electron跨平臺桌面應用就開發好了,真的 so easy!

    5、進程詳解

    5.1 基本認知

    Electron 架構和 Chromium 架構類似,也是具有1個主進程和多個渲染進程(如下圖所示)。

    但是也有區別:

    • 1)在各個進程中暴露了 Native API ,提供了 Native 能力;
    • 2)引入了 Node.js,所以可以使用 Node 的能力;
    • 3)但是渲染進程使用node 需要配置。

    可以簡單的理解為:Electron為web項目套上了Node.js環境的殼,使得我們可以調用Node.js的豐富的API。這樣我們可以用JavaScript來寫桌面應用,拓展很多我們在web端不能做的事情。

    下面這張圖,技術原理更容易理解一點:

    5.2 主進程的主要特點

    Electron 運行 package.json 的 main 腳本的進程被稱為主進程 (主進程只有一個)。涉及到具體代碼的講解,將在下一節中展開,本節就不作過多闡述了。

    Electron主進程的具體職責:

    • 1)主進程連接著操作系統和渲染進程,可以把她看做頁面和計算機溝通的橋梁;
    • 2)進程間通信、窗口管理
    • 3)全局通用服務;
    • 4)一些只能或適合在主進程做的事情(例如瀏覽器下載、全局快捷鍵處理、托盤、session);
    • 5)維護一些必要的全局狀態。

    5.3 渲染進程的主要特點

    渲染進程就是我們所熟悉前端環境了,只是載體改變了,從瀏覽器變成了window.

    注意:出于安全考慮,渲染進程是不能直接訪問本地資源的,因此都需要在主進程完成。

    Electron渲染進程主要特點:

    • 1)Electron 使用了 Chromium 來展示 web 頁面,所以 Chromium 的多進程架構也被使用到;
    • 2)每個web頁面運行在它自己的渲染進程中(每個渲染進程都是相互獨立的,并且只關心他們自己的網頁);
    • 3)使用BrowserWindow類開啟一個渲染進程并將這個實例運行在該進程中,當一個BrowserWindow實例被銷毀后,相應的渲染進程也會被終止;
    • 4)渲染進程中不能調用原生資源,但是渲染進程中同樣包含Node.js環境,所以可以引入Node.js。

    5.4 主進程與渲染進程的關系

    主進程與渲染進程的關系主要是這樣:

    • 1)主進程使用 BrowserWindow 實例創建網頁;
    • 2)每個 BrowserWindow 實例都在自己的渲染進程里運行著一個網頁(當一個 BrowserWindow 實例被銷毀后,相應的渲染進程也會被終止);
    • 3)主進程管理所有頁面和與之對應的渲染進程;
    • 4)由于在網頁里管理原生 GUI 資源是非常危險而且容易造成資源泄露,所以在網頁面調用 GUI 相關的 APIs 是不被允許的(如果你想在網頁里使用 GUI 操作,其對應的渲染進程必須與主進程進行通訊,請求主進程進行相關的 GUI 操作)。

    具體關系如下圖所示:

    把它們想象成這樣:

    即Chrome(或其他瀏覽器)的每個標簽頁(tab)及其頁面,就好比 Electron 中的一個單獨渲染進程。即使關閉所有標簽頁,Chrome 依然存在。這好比 Electron 的主進程,能打開新的窗口或關閉這個應用。就像下圖這樣。

    6、從代碼角度理解進程

    6.1 主進程和渲染進程

    先來看看 electron 項目基本目錄結構:

    app

    └─public

        └─index.html---------------入口文件

    ├─main.js----------------------程序啟動入口,主進程

    ├─ipc--------------------------進程間模塊

    ├─appNetwork-------------------應用通信模塊

    └─src--------------------------窗口管理,渲染進程

        ├─components---------------通用組件模塊

        ├─store--------------------數據共享模塊

        ├─statics------------------靜態資源模塊

        └─pages----------------------窗口業務模塊

          ├─窗口A----------------窗口

          └─窗口B----------------窗口

    如上所示:package.json 中的 main 字段對應的文件的進程是主進程。Electron集成了Chromium來展示窗口界面,窗口中所看到的內容使用的都是HTML渲染出來的。

    Chromium本身是多進程渲染頁面的架構(在默認情況下,Chromium的默認策略是對每一個tab新開一個進程,以確保每個頁面是獨立且互不影響的,避免一個頁面的崩潰導致全部頁面無法使用),所以Electron在展示窗口時,也會使用到Chromium的多進程架構。而這種多進程渲染架構在Electron中,也就被是渲染進程(render process)啦。

    6.2 進程間通信

    在 Electron 中,GUI 相關的模塊(如 dialog,menu 等)僅在主進程可用,在渲染進程中不可用。

    為了在渲染進程中使用它們,需要使用 ipc 模塊向主進程發送消息,下面是幾種進程間通訊的方法。

    1)ipcMain & ipcRenderer:

    從主進程到渲染進程的異步通信,也可以將消息從主進程發送到渲染進程(參考文檔)。

    發送消息時,事件名稱為 channel?;貜屯较r,需要設置 event.returnValue。

    將異步消息發送回發送方,可以使用 event.reply(...),這個輔助方法將自動處理來自渲染進程的消息,然而 event.sender.send(...) 這個方法則始終將消息發送給主進程。

    下面是在渲染和主進程之間發送和處理消息的一個例子:

    // 在主進程中

    const { ipcMain } = require('electron')

    ipcMain.on('asynchronous-message', (event, arg) => {

        console.log(arg); // 輸出 'ping'

        event.reply('asynchronous-reply', 'pong');

    })

    ipcMain.on('synchronous-message', (event, arg) => {

        console.log(arg) // 輸出 ‘ping’

        event.returnValue = 'pong'

    })

    // 在渲染進程(網頁)中

    const { ipcRenderer } = require('electron')

    console.log(ipcRenderer.sendSync('synchronous-message', 'ping')) // 輸出 'pong'

    ipcRenderer.on('asynchronous-reply', (event, arg) => {

        console.log(arg); // 輸出 'pong'

    })

    ipcRenderer.send('asynchronous-message', 'ping')

    2)remote 模塊:

    remote 為渲染進程和主進程通信提供了一種簡單的方法。你可以調用 main 進程對象的方法,而不必顯式發送進程間消息。

    例如:從渲染進程創建瀏覽器窗口

    const { BrowserWindow } = require('electron').remote

    let win = newBrowserWindow({ width: 800, height: 600 })

    win.loadUrl('https://www.mogu.com')

    注意: 反過來,如果需要從主進程訪問渲染進程,可以使用 webContents.executeJavascript。

    3)webContents:

    即通過 channel 向渲染進程發送異步消息,可以發送任意參數。在內部,參數會被序列化為 JSON,因此參數對象傷的函數和原型鏈不會被發送。

    除了以上這些方法,也可以使用 localStorage、sessionStorage 等。

    7、打包發布

    開發完成后,還需要將應用打包成可執行文件,這一環節的坑還是學習 electron 到現在踩的最多的。

    目前主流的打包工具有 electron-packager和 electron-builder

    7.1 electron-packager

    1)安裝依賴:

    npm i electron-packager --save-dev

    2)打包:

    electron-packager --platform= --arch= [optional flags...]

    也可以直接運行 npm run electron-packager 打包。

    7.2 electron-builder

    官方解釋:

    A complete solution to package and build a ready for distribution Electron, Proton Native or Muon app for macOS, Windows and Linux with “auto update” support out of the box.

    簡單的說:electron-builder 有比 electron-packager 更豐富的功能,支持更多的平臺,同時也支持了自動更新。除了這幾點外,electron-builder 打出的包更為輕量,并且可以打包出不暴露源碼的 setup 安裝程序。

    另外使用下來感覺比 electron-packager 的坑要少一點。

    1)安裝依賴:

    npm i electron-builder --save-dev

    2)打包(在項目的 package.json 文件中定義 build 字段):

    {

        "build": {

            "appId": "com.xxx.app",

            "extends": null,

            "files": [

                "build/**/*"

            ],

            "mac": {

                "icon": "icons/icon.icns"

            },

            "win": {

                "target": "nsis",

                "icon": "icons/icon.png"

            }

        }

    }

    這是最基礎的配置,當然打包過程中可能會碰到其他的問題需要修改配置。通常 files 配置只寫一個 build 文件夾是不夠的,要根據項目結構和打包情況添加其他路徑。

    添加 scripts 命令

    {

        "scripts": {

            "pack": "electron-builder"

        }

    }

    運行 npm run pack 打包。

    打包完成后在 dist 目錄下有可執行文件,打開后如果沒有報錯,則說明打包成功。

    8、踩坑總結

    我所遇到的大部分都是打包遇到的坑,以下列舉幾個典型的坑。

    8.1 使用 electron-packager 打包報錯

    Generated checksum for"electron-v6.0.2-darwin-x64.zip"did not match expected checksum。

    解決方法:node 版本升級到 8.x 以上就好。

    8.2 打開打包生成的可執行文件報錯

    出現這種問題可能有以下幾個原因。

    1)項目中可能直接訪問了本地路徑, 瀏覽器為了安全考慮不允許訪問。

    2)package.json 中的 build 配置問題,假如 main.js 在一個很深的路徑中,需要在下面單獨添加 main.js 的路徑:

    "build": {

        ...

    +   "public/main.js"

        ...

    }

    3)webpack 配置中的路徑直接使用了 __dirname, 可以使用 remote 模塊的 getAppPath 方法取得路徑:

    const remote = require('remote')

    const app = remote.require('app')

    console.log(app.getAppPath());

    參考資料:https://github.com/electron/electron/issues/5107

    8.3 dependencies & devDependencies

    在 Electron 打包時,一定要分清哪些是生產環境依賴,哪些是開發環境依賴,避免出現此類錯誤:

     

    8.4 關于打包慢的問題(npm & cnpm)

    cnpm 裝的各種 node_modules,這種方式下所有的包都是扁平化的安裝,一下子 node_modules 展開就有非常多的文件,導致打包的過程非常慢。

    但是如果該用 npm 來安裝 node_modules 的話,所有的包都是樹狀結構,層級變深。但是打包速度會快很多(具體資料參見:electron打包過了2小時都沒好?)。

    9、Electron的優缺點

    文章的最后,基于實踐體會,總結一下Electron的優缺點。

    Electron優點很明顯:

    • 1)上手較簡單:HTML、CSS、JS、Node 、npm包、UI框架 ,方便高效,能很輕松的實現很好看的UI;
    • 2)可多端運行:可以快速構建“跨平臺”(Windows、MacOs、Linux)的桌面級應用;
    • 3)開發時間短:相對其他跨平臺方案(如:QT、GTK+ 等),更穩定、bug少,畢竟只要瀏覽器外殼跑起來了就可以了(當然坑是少不了的);
    • 4)兼容性問題:再也不用兼容多瀏覽器(只針對谷歌,但要兼容mac、Linux)。

    Electron缺點也同樣顯而易見:

    • 1)安裝包體積大:安裝包體積略大(打包了Chromium),至少包含了一個瀏覽器的體積 ,每裝一個app就相當于裝一個chrome;
    • 2)運行性能稍差:性能不如原生應用,Mac系統下絲滑一些,Window系統就有點丟幀;
    • 3)內存占用較大:卡、啟動慢,新開一個進程,起步價就是一個NodeJS的內存開銷;
    • 4)網頁加載稍慢:loadURL加載遠程頁面白屏時間長(優化可采用 VSCode 骨架屏)。

    10、參考資料

    [1] Electron官方開發者手冊

    [2] Electron初體驗(快速開始、跨進程通信、打包、踩坑等)

    [3] Electron 基礎入門 簡單明了,看完啥都懂了

    [4] 網易云信Web端IM的聊天消息全文檢索技術實踐

    本文已同步發布于:http://www.52im.net/thread-4039-1-1.html)



    作者:Jack Jiang (點擊作者姓名進入Github)
    出處:http://www.52im.net/space-uid-1.html
    交流:歡迎加入即時通訊開發交流群 215891622
    討論:http://www.52im.net/
    Jack Jiang同時是【原創Java Swing外觀工程BeautyEye】【輕量級移動端即時通訊框架MobileIMSDK】的作者,可前往下載交流。
    本博文 歡迎轉載,轉載請注明出處(也可前往 我的52im.net 找到我)。


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    Jack Jiang的 Mail: jb2011@163.com, 聯系QQ: 413980957, 微信: hellojackjiang
    主站蜘蛛池模板: 亚洲一区二区三区丝袜| 成人免费777777被爆出| 免费在线精品视频| 中文字幕免费播放| 亚洲av无码一区二区三区天堂古代 | 国产免费黄色无码视频| 亚洲福利一区二区三区| 免费看男女下面日出水视频| 亚在线观看免费视频入口| 亚洲人成网站色7799| 亚洲精品少妇30p| 日韩成人免费aa在线看| 99视频在线精品免费观看6| 免费看一级一级人妻片| 亚洲毛片在线免费观看| 亚洲欧洲中文日韩av乱码| 青青青免费国产在线视频小草| 三级片免费观看久久| 亚洲精品亚洲人成在线播放| 亚洲熟妇av一区二区三区| 免费观看的a级毛片的网站| 久久一区二区三区免费播放| 特级一级毛片免费看| 久久精品国产亚洲av麻豆图片| 亚洲日产韩国一二三四区| 浮力影院第一页小视频国产在线观看免费 | 午夜无码A级毛片免费视频| 在线观看亚洲免费视频| 亚洲日韩国产精品无码av| 久久久久亚洲av毛片大| 全免费a级毛片免费**视频| 50岁老女人的毛片免费观看| 黄色短视频免费看| 久久久久久亚洲av无码蜜芽| 日本免费一区二区三区最新| 91香蕉国产线在线观看免费| 久久er国产精品免费观看8| 国内成人精品亚洲日本语音| 亚洲制服在线观看| 亚洲精品无码久久毛片波多野吉衣| 亚洲热妇无码AV在线播放|