跳到主要內容

建立您的第一個應用程式

學習目標

在本教學的這部分,您將學習如何設定 Electron 專案並編寫最簡化的入門應用程式。在本節結束時,您應該能夠從您的終端機以開發模式執行一個可用的 Electron 應用程式。

設定您的專案

避免使用 WSL

如果您使用的是 Windows 機器,請在遵循本教學時不要使用適用於 Linux 的 Windows 子系統 (WSL),因為您在嘗試執行應用程式時會遇到問題。

初始化您的 npm 專案

Electron 應用程式是使用 npm 建立的,其中 package.json 檔案作為進入點。首先建立一個資料夾,並使用 npm init 在其中初始化一個 npm 套件。

mkdir my-electron-app && cd my-electron-app
npm init

此命令將提示您在 package.json 中配置一些欄位。為了本教學的目的,有一些規則需要遵循

  • 進入點應該是 main.js (您很快就會建立該檔案)。
  • 作者許可證描述可以是任何值,但對於稍後的封裝是必要的。

然後,將 Electron 安裝到您應用程式的devDependencies中,這是僅用於開發的外部套件依賴項列表,在生產環境中不需要。

為什麼 Electron 是 devDependency?

這可能看起來違反直覺,因為您的生產程式碼正在執行 Electron API。但是,封裝的應用程式將會捆綁 Electron 二進制檔案,因此不需要將其指定為生產依賴項。

npm install electron --save-dev

在初始化您的套件並安裝 Electron 後,您的 package.json 檔案應該看起來像這樣。您現在也應該有一個包含 Electron 可執行檔的 node_modules 資料夾,以及一個指定要安裝的確切依賴項版本的 package-lock.json 鎖定檔案。

package.json
{
"name": "my-electron-app",
"version": "1.0.0",
"description": "Hello World!",
"main": "main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Jane Doe",
"license": "MIT",
"devDependencies": {
"electron": "23.1.3"
}
}
Electron 進階安裝步驟

如果直接安裝 Electron 失敗,請參閱我們的進階安裝文件,以取得有關下載鏡像、代理和疑難排解步驟的說明。

新增 .gitignore

.gitignore檔案指定要避免使用 Git 追蹤的檔案和目錄。您應該將GitHub 的 Node.js gitignore 範本副本放到您專案的根資料夾中,以避免提交您專案的 node_modules 資料夾。

執行 Electron 應用程式

延伸閱讀

請閱讀Electron 的進程模型文件,以更好地了解 Electron 的多個進程如何協同運作。

您在 package.json 中定義的main腳本是任何 Electron 應用程式的進入點。此腳本控制主進程,該進程在 Node.js 環境中執行,並負責控制您應用程式的生命週期、顯示原生介面、執行特權操作,以及管理渲染器進程(稍後會詳細介紹)。

在建立您的第一個 Electron 應用程式之前,您將首先使用一個簡單的腳本來確保您的主進程進入點配置正確。在您專案的根資料夾中建立一個 main.js 檔案,其中包含一行程式碼

main.js
console.log('Hello from Electron 👋')

由於 Electron 的主進程是 Node.js 執行階段,您可以使用 electron 命令執行任意的 Node.js 程式碼 (您甚至可以將其用作 REPL)。若要執行此腳本,請將 electron . 新增至 package.json 的scripts欄位中的 start 命令。此命令將告訴 Electron 可執行檔在目前目錄中尋找主腳本,並以開發模式執行。

package.json
{
"name": "my-electron-app",
"version": "1.0.0",
"description": "Hello World!",
"main": "main.js",
"scripts": {
"start": "electron .",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Jane Doe",
"license": "MIT",
"devDependencies": {
"electron": "23.1.3"
}
}
npm run start

您的終端機應該會印出 Hello from Electron 👋。恭喜您,您已經在 Electron 中執行了第一行程式碼!接下來,您將學習如何使用 HTML 建立使用者介面,並將其載入到原生視窗中。

將網頁載入到 BrowserWindow 中

在 Electron 中,每個視窗都會顯示一個網頁,該網頁可以從本機 HTML 檔案或遠端網址載入。對於此範例,您將載入本機檔案。首先,在您專案的根資料夾中的 index.html 檔案中建立一個最簡化的網頁

index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<meta
http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'"
/>
<meta
http-equiv="X-Content-Security-Policy"
content="default-src 'self'; script-src 'self'"
/>
<title>Hello from Electron renderer!</title>
</head>
<body>
<h1>Hello from Electron renderer!</h1>
<p>👋</p>
</body>
</html>

現在您有了網頁,您可以將其載入到 Electron BrowserWindow 中。將您的 main.js 檔案的內容取代為以下程式碼。我們將分別解釋每個重點區塊。

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

const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600
})

win.loadFile('index.html')
}

app.whenReady().then(() => {
createWindow()
})

匯入模組

main.js (第 1 行)
const { app, BrowserWindow } = require('electron')

在第一行中,我們使用 CommonJS 模組語法匯入兩個 Electron 模組

  • app,它控制您應用程式的事件生命週期。
  • BrowserWindow,它會建立和管理應用程式視窗。
模組大小寫慣例

您可能已經注意到 app 和 BrowserWindow 模組之間的大小寫差異。Electron 在這裡遵循典型的 JavaScript 慣例,其中 PascalCase 模組是可實例化的類別建構子 (例如 BrowserWindow、Tray、Notification),而 camelCase 模組不可實例化 (例如 app、ipcRenderer、webContents)。

類型化的匯入別名

為了在編寫 TypeScript 程式碼時進行更好的類型檢查,您可以選擇從 electron/main 匯入主進程模組。

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

如需更多資訊,請參閱進程模型文件

Electron 中的 ES 模組

從 Electron 28 版本開始,支援 ECMAScript 模組 (也就是使用 import 來載入模組)。您可以在我們的 ESM 指南中找到更多關於 Electron 中 ESM 的狀態以及如何在應用程式中使用它們的資訊。

撰寫可重複使用的函數來實例化視窗

createWindow() 函數會將您的網頁載入到新的 BrowserWindow 實例中

main.js (第 3-10 行)
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600
})

win.loadFile('index.html')
}

在應用程式準備就緒時呼叫您的函數

main.js (第 12-14 行)
app.whenReady().then(() => {
createWindow()
})

許多 Electron 的核心模組都是 Node.js 的事件發射器,它們遵循 Node 的非同步事件驅動架構。app 模組就是這些發射器之一。

在 Electron 中,只有在 app 模組的 ready 事件觸發後才能建立 BrowserWindow。您可以使用 app.whenReady() API 來等待此事件,並在其 promise 完成後呼叫 createWindow()

資訊

您通常可以使用發射器的 .on 函數來監聽 Node.js 事件。

+ app.on('ready', () => {
- app.whenReady().then(() => {
createWindow()
})

然而,Electron 將 app.whenReady() 作為一個輔助函數,專門用於處理 ready 事件,以避免直接監聽該特定事件時的細微陷阱。詳細資訊請參閱 electron/electron#21972

此時,執行您的 Electron 應用程式的 start 命令應該會成功開啟一個視窗,顯示您的網頁!

您的應用程式在視窗中顯示的每個網頁都會在一個稱為 **渲染器** 處理程序(或簡稱 _renderer_)的獨立處理程序中執行。渲染器處理程序可以存取您用於典型前端網頁開發的相同 JavaScript API 和工具,例如使用 webpack 來捆綁和壓縮程式碼,或使用 React 來建構您的使用者介面。

管理您應用程式的視窗生命週期

應用程式視窗在每個作業系統上的行為都不同。Electron 並不強制預設採用這些慣例,而是讓您可以選擇是否在應用程式程式碼中實作這些慣例。您可以透過監聽 app 和 BrowserWindow 模組發出的事件來實作基本的視窗慣例。

特定於處理程序的控制流程

檢查 Node 的 process.platform 變數可以幫助您在特定平台上有條件地執行程式碼。請注意,Electron 只能在三個可能的平台上執行:win32 (Windows)、linux (Linux) 和 darwin (macOS)。

當所有視窗關閉時退出應用程式 (Windows 和 Linux)

在 Windows 和 Linux 上,關閉所有視窗通常會完全退出應用程式。若要在您的 Electron 應用程式中實作此模式,請監聽 app 模組的 window-all-closed 事件,並在使用者不是使用 macOS 時呼叫 app.quit() 來退出您的應用程式。

app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})

如果沒有開啟視窗則開啟視窗 (macOS)

相反地,macOS 應用程式通常即使沒有開啟任何視窗也會繼續執行。當沒有視窗可用時,啟用應用程式應該會開啟一個新的視窗。

若要實作此功能,請監聽 app 模組的 activate 事件,並且在沒有開啟任何 BrowserWindow 時呼叫您現有的 createWindow() 方法。

由於視窗必須在 ready 事件之後才能建立,因此您應該僅在應用程式初始化後才監聽 activate 事件。請僅在您現有的 whenReady() 回呼函數內監聽 activate 事件,即可達成此目的。

app.whenReady().then(() => {
createWindow()

app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})

最終的起始程式碼

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

const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600
})

win.loadFile('index.html')
}

app.whenReady().then(() => {
createWindow()

app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
})

app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})

選用:從 VS Code 進行除錯

如果您想要使用 VS Code 來除錯您的應用程式,您需要將 VS Code 連接至主處理程序和渲染器處理程序。以下是一個範例組態供您執行。在您的專案中的新 .vscode 資料夾中建立一個 launch.json 組態

.vscode/launch.json
{
"version": "0.2.0",
"compounds": [
{
"name": "Main + renderer",
"configurations": ["Main", "Renderer"],
"stopAll": true
}
],
"configurations": [
{
"name": "Renderer",
"port": 9222,
"request": "attach",
"type": "chrome",
"webRoot": "${workspaceFolder}"
},
{
"name": "Main",
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}",
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron",
"windows": {
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd"
},
"args": [".", "--remote-debugging-port=9222"],
"outputCapture": "std",
"console": "integratedTerminal"
}
]
}

當您從側邊欄選取「執行和除錯」時,會出現「主處理程序 + 渲染器」選項,讓您可以設定中斷點,並檢查主處理程序和渲染器處理程序中的所有變數等內容。

我們在 launch.json 檔案中所做的是建立 3 個組態

  • Main 用於啟動主處理程序,並公開連接埠 9222 以進行遠端除錯 (--remote-debugging-port=9222)。這是我們將用來連接 Renderer 的偵錯工具的連接埠。因為主處理程序是一個 Node.js 處理程序,所以類型設定為 node
  • Renderer 用於除錯渲染器處理程序。因為主處理程序是建立該處理程序的處理程序,所以我們必須「連接」到它 ("request": "attach") 而不是建立新的處理程序。渲染器處理程序是一個網頁處理程序,因此我們必須使用的偵錯工具是 chrome
  • Main + renderer 是一個複合任務,會同時執行先前的任務。
注意

由於我們正在 Renderer 中連接到一個處理程序,因此可能會跳過您程式碼的第一行,因為偵錯工具在執行程式碼之前沒有足夠的時間連線。您可以在開發模式下重新整理頁面或設定逾時,來解決這個問題。

延伸閱讀

如果您想要更深入地研究偵錯領域,以下指南提供了更多資訊

摘要

Electron 應用程式是使用 npm 套件設定的。Electron 可執行檔應安裝在您專案的 devDependencies 中,並可以使用 package.json 檔案中的腳本在開發模式下執行。

該可執行檔會執行您 package.json 的 main 屬性中找到的 JavaScript 進入點。此檔案控制 Electron 的**主處理程序**,該處理程序會執行 Node.js 的實例,並負責您應用程式的生命週期、顯示原生介面、執行特權操作以及管理渲染器處理程序。

**渲染器處理程序**(或簡稱渲染器)負責顯示圖形內容。您可以透過將其指向網址或本機 HTML 檔案,將網頁載入到渲染器中。渲染器的行為與一般網頁非常相似,並且可以存取相同的網頁 API。

在本教學的下一節中,我們將學習如何使用特權 API 來擴增渲染器處理程序,以及如何在處理程序之間進行通訊。