Webpack實戰-構建 Electron 應用

認識 Electron

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

Electron 是 Node.js 和 Chromium 瀏覽器的結合體,用 Chromium 瀏覽器顯示出的 Web 頁面做爲應用的 GUI,經過 Node.js 去和操做系統交互。 當你在 Electron 應用中的一個窗口操做時,其實是在操做一個網頁。當你的操做須要經過操做系統去完成時,網頁會經過 Node.js 去和操做系統交互。html

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

  • 下降開發門檻,只需掌握網頁開發技術和 Node.js 便可,大量的 Web 開發技術和現成庫能夠複用於 Electron;
  • 因爲 Chromium 瀏覽器和 Node.js 都是跨平臺的,Electron 能作到寫一份代碼在不一樣的操做系統運行。

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

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()
  }
})
複製代碼

主進程啓動後會一直駐留在後臺運行,你眼睛所看得的和操做的窗口並非主進程,而是由主進程新啓動的窗口子進程。git

應用從啓動到退出有一系列生命週期事件,經過 electron.app.on() 函數去監聽生命週期事件,在特定的時刻作出反應。 例如在 app.on('ready') 事件中經過 BrowserWindow 去展現應用的主窗口,具體用法見 BrowserWindow 的 API 文檔github

啓動的窗口實際上是一個網頁,啓動時會去加載在 loadURL 中傳入的網頁地址。 每一個窗口都是一個單獨的網頁進程,窗口之間的通訊須要藉助主進程傳遞消息。web

Electron 應用架構圖

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

接入 Webpack

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

因爲 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 . 你就能成功看到啓動的桌面應用了,效果如圖:

Electron 應用運行效果圖

本實例提供項目完整代碼

《深刻淺出Webpack》全書在線閱讀連接

閱讀原文

相關文章
相關標籤/搜索