建立您的第一個應用程式
學習目標
在本教學的這部分,您將學習如何設定 Electron 專案並編寫最簡化的入門應用程式。在本節結束時,您應該能夠從您的終端機以開發模式執行一個可用的 Electron 應用程式。
設定您的專案
如果您使用的是 Windows 機器,請在遵循本教學時不要使用適用於 Linux 的 Windows 子系統 (WSL),因為您在嘗試執行應用程式時會遇到問題。
初始化您的 npm 專案
Electron 應用程式是使用 npm 建立的,其中 package.json 檔案作為進入點。首先建立一個資料夾,並使用 npm init
在其中初始化一個 npm 套件。
- npm
- Yarn
mkdir my-electron-app && cd my-electron-app
npm init
mkdir my-electron-app && cd my-electron-app
yarn init
此命令將提示您在 package.json 中配置一些欄位。為了本教學的目的,有一些規則需要遵循
- 進入點應該是
main.js
(您很快就會建立該檔案)。 - 作者、許可證和描述可以是任何值,但對於稍後的封裝是必要的。
然後,將 Electron 安裝到您應用程式的devDependencies中,這是僅用於開發的外部套件依賴項列表,在生產環境中不需要。
這可能看起來違反直覺,因為您的生產程式碼正在執行 Electron API。但是,封裝的應用程式將會捆綁 Electron 二進制檔案,因此不需要將其指定為生產依賴項。
- npm
- Yarn
npm install electron --save-dev
yarn add electron --dev
在初始化您的套件並安裝 Electron 後,您的 package.json 檔案應該看起來像這樣。您現在也應該有一個包含 Electron 可執行檔的 node_modules
資料夾,以及一個指定要安裝的確切依賴項版本的 package-lock.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 失敗,請參閱我們的進階安裝文件,以取得有關下載鏡像、代理和疑難排解步驟的說明。
新增 .gitignore
.gitignore
檔案指定要避免使用 Git 追蹤的檔案和目錄。您應該將GitHub 的 Node.js gitignore 範本副本放到您專案的根資料夾中,以避免提交您專案的 node_modules
資料夾。
執行 Electron 應用程式
請閱讀Electron 的進程模型文件,以更好地了解 Electron 的多個進程如何協同運作。
您在 package.json 中定義的main
腳本是任何 Electron 應用程式的進入點。此腳本控制主進程,該進程在 Node.js 環境中執行,並負責控制您應用程式的生命週期、顯示原生介面、執行特權操作,以及管理渲染器進程(稍後會詳細介紹)。
在建立您的第一個 Electron 應用程式之前,您將首先使用一個簡單的腳本來確保您的主進程進入點配置正確。在您專案的根資料夾中建立一個 main.js
檔案,其中包含一行程式碼
console.log('Hello from Electron 👋')
由於 Electron 的主進程是 Node.js 執行階段,您可以使用 electron
命令執行任意的 Node.js 程式碼 (您甚至可以將其用作 REPL)。若要執行此腳本,請將 electron .
新增至 package.json 的scripts
欄位中的 start
命令。此命令將告訴 Electron 可執行檔在目前目錄中尋找主腳本,並以開發模式執行。
{
"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
- Yarn
npm run start
yarn run start
您的終端機應該會印出 Hello from Electron 👋
。恭喜您,您已經在 Electron 中執行了第一行程式碼!接下來,您將學習如何使用 HTML 建立使用者介面,並將其載入到原生視窗中。
將網頁載入到 BrowserWindow 中
在 Electron 中,每個視窗都會顯示一個網頁,該網頁可以從本機 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
檔案的內容取代為以下程式碼。我們將分別解釋每個重點區塊。
const { app, BrowserWindow } = require('electron')
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600
})
win.loadFile('index.html')
}
app.whenReady().then(() => {
createWindow()
})
匯入模組
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 28 版本開始,支援 ECMAScript 模組 (也就是使用 import
來載入模組)。您可以在我們的 ESM 指南中找到更多關於 Electron 中 ESM 的狀態以及如何在應用程式中使用它們的資訊。
撰寫可重複使用的函數來實例化視窗
createWindow()
函數會將您的網頁載入到新的 BrowserWindow 實例中
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600
})
win.loadFile('index.html')
}
在應用程式準備就緒時呼叫您的函數
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()
})
})
最終的起始程式碼
- main.js
- index.html
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()
}
})
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<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>
<p id="info"></p>
</body>
<script src="./renderer.js"></script>
</html>
選用:從 VS Code 進行除錯
如果您想要使用 VS Code 來除錯您的應用程式,您需要將 VS Code 連接至主處理程序和渲染器處理程序。以下是一個範例組態供您執行。在您的專案中的新 .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 來擴增渲染器處理程序,以及如何在處理程序之間進行通訊。