在本節(jié),您會學習如何創(chuàng)建您的 Electron 項目,并且編寫一個簡單的入門程序。 到了本節(jié)末尾,您應該能夠在終端開發(fā)環(huán)境運行一個 Electron 應用。
避免使用 WSL
如果您用的是 Windows,在本教程中請不要使用 Windows Subsystem for Linux (WSL),否則您在運行應用時可能會遇到問題。
Electron 應用基于 npm 搭建,以 package.json 文件作為入口點。 首先創(chuàng)建一個文件夾,然后在其中執(zhí)行 npm init
初始化項目。
npm | Yarn |
|
|
這條命令會幫您配置 package.json 中的一些字段。 為本教程的目的,有幾條規(guī)則需要遵循:
main.js
(您很快就會創(chuàng)建它)然后,將 Electron 安裝為您項目的 devDependencies,即僅在開發(fā)環(huán)境需要的額外依賴。
為什么 ELECTRON 是 DEVDEPENDENCY?
您的應用需要運行 Electron API,因此這聽上去可能有點反直覺。 實際上,打包后的應用本身會包含 Electron 的二進制文件,因此不需要將 Electron 作為生產(chǎn)環(huán)境依賴。
npm | Yarn |
|
|
在初始化并且安裝完 Electron 之后,您的 package.json 應該長下面這樣。 文件夾中會出現(xiàn)一個 node_modules
文件夾,其中包含了 Electron 可執(zhí)行文件;還有一個 package-lock.json
文件,指定了各個依賴的確切版本。
{
"name": "my-electron-app",
"version": "1.0.0",
"description": "Hello World!",
"main": "main.js",
"author": "Jane Doe",
"license": "MIT",
"devDependencies": {
"electron": "19.0.0"
}
}
高級安裝步驟
如果直接安裝 Electron 失敗,請參閱我們的 安裝指導 文檔,里面包含下載鏡像、代理和故障排除等信息。
.gitignore
指定了哪些文件不需要 Git 追蹤版本。 建議您復制一份 GitHub 的 Node.js gitignore 模板 到您項目的根目錄,以避免將 node_modules
文件夾提交到版本控制系統(tǒng)中。
:::延伸閱讀
參閱 流程模型 相關文檔來了解 Electron 的進程之間是如何協(xié)作的。
:::
您在 package.json 中指定的腳本文件 main
是所有 Electron 應用的入口點。 這個文件控制 主程序 (main process),它運行在 Node.js 環(huán)境里,負責控制您應用的生命周期、顯示原生界面、執(zhí)行特殊操作并管理渲染器進程
(renderer processes),稍后會詳細介紹。
在繼續(xù)編寫您的 Electron 應用之前,您將使用一個小小的腳本來確保主進程入口點已經(jīng)配置正確。 在根目錄的 main.js
文件中寫一行代碼:
console.log(`歡迎來到 Electron `)
因為 Electron 的主進程是一個 Node.js 運行時,您可以使用 electron
命令執(zhí)行任意 Node.js 代碼(甚至將其用作 REPL)。 要執(zhí)行這個腳本,在 package.json 的 scripts
字段中添加一個 start
命令,執(zhí)行內(nèi)容為 electron .
。
這個命令會告訴 Electron 在當前目錄下尋找主腳本,并以開發(fā)模式運行它。
{
"name": "my-electron-app",
"version": "1.0.0",
"description": "Hello World!",
"main": "main.js",
"author": "Jane Doe",
"license": "MIT",
"scripts": {
"start": "electron ."
},
"devDependencies": {
"electron": "^19.0.0"
}
}
npm | Yarn |
|
|
您的終端應該會輸出 歡迎來到 Electron
。 恭喜,您已經(jīng)在 Electron 中執(zhí)行了您的第一行代碼! 接下來,您會學習如何用 HTML 創(chuàng)建用戶界面,并將它們裝載到原生窗口中。
在 Electron 中,每個窗口展示一個頁面,后者可以來自本地的 HTML,也可以來自遠程 URL。 在本例中,您將會裝載本地的文件。 在您項目的根目錄中創(chuàng)建一個 index.html
文件,并寫入下面的內(nèi)容:
<!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>
現(xiàn)在您有了一個網(wǎng)頁,可以將它裝載到 Electron 的 BrowserWindow 上了。 將 main.js
中的內(nèi)容替換成下列代碼。 我們馬上會逐行解釋。
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 兩個模塊名的大小寫差異。 Electron 遵循 JavaScript 傳統(tǒng)約定,以帕斯卡命名法 (PascalCase) 命名可實例化的類 (如 BrowserWindow, Tray 和 Notification),以駝峰命名法 (camelCase) 命名不可實例化的函數(shù)、變量等 (如 app, ipcRenderer, webContents) 。
在 ELECTRON 中使用 ES 語法
Electron 目前對 ECMAScript 語法 (如使用
import
來導入模塊) 的支持還不完善。 您可以在 electron/electron#21457 這個 issue 中查看 ESM 的適配進展。
createWindow()
函數(shù)將您的頁面加載到新的 BrowserWindow 實例中:
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600,
})
win.loadFile('index.html')
}
app.whenReady().then(() => {
createWindow()
})
Electron 的很多核心模組是 Node.js 事件觸發(fā)器,遵守 Node.js 的異步事件驅(qū)動架構。 app 模塊就是其中一個。
在 Electron 中,只有在 app 模組的 ?ready
? 事件能觸發(fā)后才能創(chuàng)建 BrowserWindows 實例。 您可以借助 ?app.whenReady()
? API 來等待此事件,并在該 API 的 promise 被 resolve 時調(diào)用 createWindow()
方法。
INFO
通常我們使用觸發(fā)器的
.on
函數(shù)來監(jiān)聽 Node.js 事件。
+ app.on('ready').then(() => { - app.whenReady().then(() => { createWindow() })
但是 Electron 暴露了
app.whenReady()
方法,作為其ready
事件的專用監(jiān)聽器,這樣可以避免直接監(jiān)聽 .on 事件帶來的一些問題。 參見 electron/electron#21972 。
此時,運行 start
命令應該能成功地打開一個包含您網(wǎng)頁內(nèi)容的窗口!
您應用中的每個頁面都在一個單獨的進程中運行,我們稱這些進程為 渲染器 (renderer) 。 渲染器也能訪問前端開發(fā)常會用到的 API 和工具,例如用于打包并壓縮代碼的 webpack,還有用于構建用戶界面的 React 。
應用窗口在不同操作系統(tǒng)中的行為也不同。 Electron 允許您自行實現(xiàn)這些行為來遵循操作系統(tǒng)的規(guī)范,而不是采用默認的強制執(zhí)行。 您可以通過監(jiān)聽 app 和 BrowserWindow 模組的事件,自行實現(xiàn)基礎的應用窗口規(guī)范。
針對特定進程的控制流
可以檢查 Node.js 的
process.platform
變量,幫助您在不同操作系統(tǒng)上運行特定代碼。 請注意,Electron 目前只支持三個平臺:win32
(Windows),linux
(Linux) 和darwin
(macOS) 。
在 Windows 和 Linux 上,我們通常希望在關閉一個應用的所有窗口后讓它退出。 若要在 Electron 中實現(xiàn)這一點,您可以監(jiān)聽 ?window-all-closed
? 事件,并調(diào)用 ?app.quit()
? 來讓應用退出。這不適用于 macOS。
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
與前二者相比,即使沒有打開任何窗口,macOS 應用通常也會繼續(xù)運行。 在沒有窗口可用時調(diào)用 app 會打開一個新窗口。
為了實現(xiàn)這一特性,可以監(jiān)聽模組的 ?activate
? 事件,如果沒有任何活動的 BrowserWindow,調(diào)用 createWindow()
方法新建一個。
因為窗口無法在 ready
事件前創(chuàng)建,你應當在你的應用初始化后僅監(jiān)聽 activate
事件。 要實現(xiàn)這個,僅監(jiān)聽 whenReady()
回調(diào)即可。
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
main.js | index.html |
|
|
DOCS/FIDDLES/TUTORIAL-FIRST-APP (22.0.2)
如果您希望使用 VS Code 調(diào)試您的程序,您需要讓 VS Code 監(jiān)聽主進程 (main process) 和渲染器進程 (renderer process) 。 下面為您提供了一個簡單的配置文件。 請在根目錄新建一個 .vscode
文件夾,然后在其中新建一個 launch.json 配置文件并填寫如下內(nèi)容。
{
"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"
}
]
}
保存后,當您選擇側邊欄的 “運行和調(diào)試”,將會出現(xiàn)一個 "Main + renderer" 選項。然后您便可設置斷點,并跟蹤主進程和渲染器進程中的所有變量。
上文中我們在 launch.json
所做的其實是創(chuàng)建三個配置項:
Main
用來運行主程序,并且暴露出 9222 端口用于遠程調(diào)試 (--remote-debugging-port=9222
) 。 我們將把調(diào)試器綁定到那個端口來調(diào)試 renderer
。 因為主進程是 Node.js 進程,類型被設置為 node
。Renderer
用來調(diào)試渲染器進程。 因為后者是由主進程創(chuàng)建的,我們要把它 “綁定” 到主進程上 ()"request": "attach"
,而不是創(chuàng)建一個新的。 渲染器是 web 進程,因此要選擇 chrome
調(diào)試器。Main + renderer
是一個 復合任務,可同時執(zhí)行前兩個任務。注意事項
由于我們要將進程綁定到
Renderer
任務,您應用中的前幾行代碼可能會被跳過,因為調(diào)試器 (Debugger) 在執(zhí)行代碼之前沒有足夠的時間進行連接。 在開發(fā)環(huán)境中,您可以通過刷新頁面或者使用 setTimeout 延遲運行代碼,來避開這個問題。
延伸閱讀
如果您希望深挖調(diào)試步驟,可以查看以下指南:
開發(fā)者工具擴展
Electron 程序是通過 npm 包創(chuàng)建的。 您應將 Electron 依賴安裝到 devDependencies
,然后在 package.json 中設置一個腳本來運行。
執(zhí)行命令后,Electron 程序會運行您在 package.json 文件的 main
字段設置的入口文件。 這個入口文件控制著 Electron 的主進程,后者運行于 Node.js 實例,負責應用的生命周期、展示原生窗口、執(zhí)行特殊操作和管理渲染進程。
渲染器進程(簡稱渲染器) 負責展示圖形內(nèi)容。 您可以將渲染的網(wǎng)頁指向 web 地址或本地 HTML 文件。 渲染器和常規(guī)的網(wǎng)頁行為很相似,訪問的 web API 也相同。
在教程下一節(jié),我們將會學習如何使用 API 給渲染器提權,以及如何在進程間通信。
更多建議: