標籤:

Webpack實戰-構建 Electron 應用

認識 Electron

Electron 可以讓你使用開發 Web 的技術去開發跨平台的桌面端應用,由 Github 主導和開源,大家熟悉的 Atom 和 VSCode 編輯器就是使用 Electron 開發的。

Electron 是 Node.js 和 Chromium 瀏覽器的結合體,用 Chromium 瀏覽器顯示出的 Web 頁面作為應用的 GUI,通過 Node.js 去和操作系統交互。

當你在 Electron 應用中的一個窗口操作時,實際上是在操作一個網頁。當你的操作需要通過操作系統去完成時,網頁會通過 Node.js 去和操作系統交互。

採用這種方式開發桌面端應用的優點有:

  • 降低開發門檻,只需掌握網頁開發技術和 Node.js 即可,大量的 Web 開發技術和現成庫可以復用於 Electron;
  • 由於 Chromium 瀏覽器和 Node.js 都是跨平台的,Electron 能做到寫一份代碼在不同的操作系統運行。

在運行 Electron 應用時,會從啟動一個主進程開始。主進程的啟動是通過 Node.js 去執行一個入口 JavaScript 文件實現的,這個入口文件 main.js 內容如下:

const { app, BrowserWindow } = require(electron)// 保持一個對於 window 對象的全局引用,如果你不這樣做,// 當 JavaScript 對象被垃圾回收, window 會被自動地關閉let win// 打開主窗口function createWindow() { // 創建瀏覽器窗口 win = new BrowserWindow({ width: 800, height: 600 }) // 載入應用的 index.html const indexPageURL = `file://${__dirname}/dist/index.html`; win.loadURL(indexPageURL); // 當 window 被關閉,這個事件會被觸發 win.on(closed, () => { // 取消引用 window 對象 win = null })}// Electron 會在創建瀏覽器窗口時調用這個函數。app.on(ready, createWindow)// 當全部窗口關閉時退出app.on(window-all-closed, () => { // 在 macOS 上,除非用戶用 Cmd + Q 確定地退出 // 否則絕大部分應用會保持激活 if (process.platform !== darwin) { app.quit() }})

主進程啟動後會一直駐留在後台運行,你眼睛所看得的和操作的窗口並不是主進程,而是由主進程新啟動的窗口子進程。

應用從啟動到退出有一系列生命周期事件,通過 electron.app.on() 函數去監聽生命周期事件,在特定的時刻做出反應。

例如在 app.on(ready) 事件中通過 BrowserWindow 去展示應用的主窗口,具體用法見 BrowserWindow 的 API 文檔。

啟動的窗口其實是一個網頁,啟動時會去載入在 loadURL 中傳入的網頁地址。

每個窗口都是一個單獨的網頁進程,窗口之間的通信需要藉助主進程傳遞消息。

總體來說開發 Electron 應用和開發 Web 應用很相似,區別在於 Electron 的運行環境同時內置了瀏覽器和 Node.js 的 API,在開發網頁時除了可以使用瀏覽器提供的 API 外,還可以使用 Node.js 提供的 API。

接入 Webpack

接下來做一個簡單的 Electron 應用,要求為應用啟動後顯示一個主窗口,在主窗口裡有一個按鈕,點擊這個按鈕後新顯示一個窗口,且使用 React 開發網頁。

由於 Electron 應用中的每一個窗口對應一個網頁,所以需要開發2個網頁,分別是主窗口的 index.html 和新打開的窗口 login.html

也就是說項目由2個單頁應用組成,這和3-10管理多個單頁應用 中的項目非常相似,讓我們來把它改造成一個 Electron 應用。

需要改動的地方如下:

  • 在項目根目錄下新建主進程的入口文件 main.js,內容和上面提到的一致;
  • 主窗口網頁的代碼如下:

import React, { Component } from react;import { render } from react-dom;import { remote } from electron;import path from path;import ./index.css;class App extends Component { // 在按鈕被點擊時 handleBtnClick() { // 新窗口對應的頁面的 URI 地址 const modalPath = path.join(file://, remote.app.getAppPath(), dist/login.html); // 新窗口的大小 let win = new remote.BrowserWindow({ width: 400, height: 320 }) win.on(close, function () { // 窗口被關閉時清空資源 win = null }) // 載入網頁 win.loadURL(modalPath) // 顯示窗口 win.show() } render() { return ( <div> <h1>Page Index</h1> <button onClick={this.handleBtnClick}>Open Page Login</button> </div> ) }}render(<App/>, window.document.getElementById(app));

其中最關鍵的部分在於在按鈕點擊事件里通過 electron 庫里提供的 API 去新打開一個窗口,並載入網頁文件所在的地址。

頁面部分的代碼已經修改完成,接下來修改構建方面的代碼。

這裡構建需要做到以下幾點:

  • 構建出2個可在瀏覽器里運行的網頁,分別對應2個窗口的界面;
  • 由於在網頁的 JavaScript 代碼里可能會有調用 Node.js 原生模塊或者 electron 模塊,也就是輸出的代碼依賴這些模塊。但由於這些模塊都是內置支持的,構建出的代碼不能把這些模塊打包進去。

要完成以上要求非常簡單,因為 Webpack 內置了對 Electron 的支持。

只需要給 Webpack 配置文件加上一行代碼即可,如下:

target: electron-renderer,

這句配置曾在2-7其它配置項-Target中提到,意思是指讓 Webpack 構建出用於 Electron 渲染進程用的 JavaScript 代碼,也就是這2個窗口需要的網頁代碼。

以上修改都完成後重新執行 Webpack 構建,對應的網頁需要的代碼都輸出到了項目根目錄下的 dist 目錄里。

為了以 Electron 應用的形式運行,還需要安裝新依賴:

# 安裝 Electron 執行環境到項目中npm i -D electron

安裝成功後在項目目錄下執行 electron . 你就能成功看到啟動的桌面應用了,效果如圖:

本實例提供項目完整代碼

《深入淺出Webpack》全書在線閱讀鏈接

閱讀原文


推薦閱讀:

上傳一個nodeblink的demo,試玩一下
bElectron bAPI Demos 項目解析
史上最小巧的山寨精簡版electron-0.0001版出來啦

TAG:webpack | Electron |