本指南將會通過使用Electron創(chuàng)建一個極簡的 Hello World 應(yīng)用一步步的帶你了解,該應(yīng)用與electron/electron-quick-start類似。
通過這個教程,你的app將會打開一個瀏覽器窗口,來展示包含當前正在運行的 Chromium, Node.js與 Electronweb等版本信息的web界面
在使用Electron進行開發(fā)之前,您需要安裝 Node.js。 我們建議您使用最新的LTS版本。
請使用為你平臺預(yù)構(gòu)建的 Node.js 安裝器來進行安裝, 否則,您可能會遇到與不同開發(fā)工具不兼容的問題。
要檢查 Node.js 是否正確安裝,請在您的終端輸入以下命令:
node -v
npm -v
這兩個命令應(yīng)輸出了 Node.js 和 npm 的版本信息。
注意 因為 Electron 將 Node.js 嵌入到其二進制文件中,你應(yīng)用運行時的 Node.js 版本與你系統(tǒng)中運行的 Node.js 版本無關(guān)。
Electron 應(yīng)用程序遵循與其他 Node.js 項目相同的結(jié)構(gòu)。 首先創(chuàng)建一個文件夾并初始化 npm 包。
npm | Yarn |
|
|
init
初始化命令會提示您在項目初始化配置中設(shè)置一些值 為本教程的目的,有幾條規(guī)則需要遵循:
entry point
? 應(yīng)為 ?main.js
?.author
? 與 ?description
? 可為任意值,但對于應(yīng)用打包是必填項。你的 package.json
文件應(yīng)該像這樣:
{
"name": "my-electron-app",
"version": "1.0.0",
"description": "Hello World!",
"main": "main.js",
"author": "Jane Doe",
"license": "MIT"
}
然后,將 electron
包安裝到應(yīng)用的開發(fā)依賴中。
npm | Yarn |
|
|
注意:如果您在安裝 Electron 時遇到任何問題,請參見 安裝指導(dǎo) 指南。
最后,您希望能夠執(zhí)行 Electron 如下所示,在您的 package.json
配置文件中的scripts
字段下增加一條start
命令:
{
"scripts": {
"start": "electron ."
}
}
start
命令能讓您在開發(fā)模式下打開您的應(yīng)用
npm | Yarn |
|
|
注意:此腳本將告訴 Electron 在您項目根目錄運行 此時,您的應(yīng)用將立即拋出一個錯誤提示您它無法找到要運行的應(yīng)用
任何 Electron 應(yīng)用程序的入口都是 main
文件。 這個文件控制了主進程,它運行在一個完整的Node.js環(huán)境中,負責控制您應(yīng)用的生命周期,顯示原生界面,執(zhí)行特殊操作并管理渲染器進程(稍后詳細介紹)。
執(zhí)行期間,Electron 將依據(jù)應(yīng)用中 package.json
配置下main
字段中配置的值查找此文件,您應(yīng)該已在應(yīng)用腳手架步驟中配置。
要初始化這個main
文件,需要在您項目的根目錄下創(chuàng)建一個名為main.js
的空文件。
注意:如果您此時再次運行?
start
?命令,您的應(yīng)用將不再拋出任何錯誤! 然而,它不會做任何事因為我們還沒有在?main.js
?中添加任何代碼。
在可以為我們的應(yīng)用創(chuàng)建窗口前,我們需要先創(chuàng)建加載進該窗口的內(nèi)容。 在Electron中,各個窗口顯示的內(nèi)容可以是本地HTML文件,也可以是一個遠程url。
此教程中,您將采用本地HTML的方式。 在您的項目根目錄下創(chuàng)建一個名為index.html
的文件:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CSP -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<title>你好!</title>
</head>
<body>
<h1>你好!</h1>
我們正在使用 Node.js <span id="node-version"></span>,
Chromium <span id="chrome-version"></span>,
和 Electron <span id="electron-version"></span>.
</body>
</html>
注意:在這個HTML文本中,您會發(fā)現(xiàn)主體文本中丟失了版本編號。 稍后我們將使用 JavaScript 動態(tài)插入它們。
現(xiàn)在您有了一個頁面,將它加載進應(yīng)用窗口中。 要做到這一點,你需要 兩個Electron模塊:
app
? 模塊,它控制應(yīng)用程序的事件生命周期。BrowserWindow
? 模塊,它創(chuàng)建和管理應(yīng)用程序 窗口。因為主進程運行著 Node.js,您可以在 main.js 文件頭部將它們導(dǎo)入作為 CommonJS 模塊:
const { app, BrowserWindow } = require('electron')
然后,添加一個createWindow()
方法來將index.html
加載進一個新的BrowserWindow
實例。
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600
})
win.loadFile('index.html')
}
接著,調(diào)用createWindow()
函數(shù)來打開您的窗口。
在 Electron 中,只有在 app
模塊的 ?ready
? 事件被激發(fā)后才能創(chuàng)建瀏覽器窗口。 您可以通過使用 ?app.whenReady()
? API來監(jiān)聽此事件。 在whenReady()
成功后調(diào)用createWindow()
。
app.whenReady().then(() => {
createWindow()
})
注意:此時,您的電子應(yīng)用程序應(yīng)當成功打開顯示您頁面的窗口!
雖然你現(xiàn)在可以打開一個瀏覽器窗口,但你還需要一些額外的模板代碼使其看起來更像是各平臺原生的。 應(yīng)用程序窗口在每個OS下有不同的行為,Electron將在app中實現(xiàn)這些約定的責任交給開發(fā)者們。
一般而言,你可以使用 進程
全局的 platform
屬性來專門為某些操作系統(tǒng)運行代碼。
在Windows和Linux上,關(guān)閉所有窗口通常會完全退出一個應(yīng)用程序。
為了實現(xiàn)這一點,你需要監(jiān)聽 app
模塊的 window-all-closed
? 事件。如果用戶不是在 macOS(darwin
) 上運行程序,則調(diào)用 ?app.quit()
?。
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
當 Linux 和 Windows 應(yīng)用在沒有窗口打開時退出了,macOS 應(yīng)用通常即使在沒有打開任何窗口的情況下也繼續(xù)運行,并且在沒有窗口可用的情況下激活應(yīng)用時會打開新的窗口。
為了實現(xiàn)這一特性,監(jiān)聽 app
模塊的 ?activate
? 事件。如果沒有任何瀏覽器窗口是打開的,則調(diào)用 createWindow()
方法。
因為窗口無法在 ready
事件前創(chuàng)建,你應(yīng)當在你的應(yīng)用初始化后僅監(jiān)聽 activate
事件。 通過在您現(xiàn)有的 whenReady()
回調(diào)中附上您的事件監(jiān)聽器來完成這個操作。
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
注意:此時,您的窗口控件應(yīng)功能齊全!
現(xiàn)在,最后要做的是輸出Electron的版本號和它的依賴項到你的web頁面上。
在主進程通過Node的全局 process
對象訪問這個信息是微不足道的。 然而,你不能直接在主進程中編輯DOM,因為它無法訪問渲染器 文檔
上下文。 它們存在于完全不同的進程!
注意:如果您需要更深入地了解Electron進程,請參閱 進程模型 文檔。
這是將 預(yù)加載 腳本連接到渲染器時派上用場的地方。 預(yù)加載腳本在渲染器進程加載之前加載,并有權(quán)訪問兩個 渲染器全局 (例如 window
和 document
) 和 Node.js 環(huán)境。
創(chuàng)建一個名為 preload.js
的新腳本如下:
window.addEventListener('DOMContentLoaded', () => {
const replaceText = (selector, text) => {
const element = document.getElementById(selector)
if (element) element.innerText = text
}
for (const dependency of ['chrome', 'node', 'electron']) {
replaceText(`${dependency}-version`, process.versions[dependency])
}
})
上面的代碼訪問 Node.js process.versions
對象,并運行一個基本的 replaceText
輔助函數(shù)將版本號插入到 HTML 文檔中。
要將此腳本附加到渲染器流程,請在你現(xiàn)有的 BrowserWindow
構(gòu)造器中將路徑中的預(yù)加載腳本傳入 webPreferences.preload
選項。
// 需在當前文件內(nèi)開頭引入 Node.js 的 'path' 模塊
const path = require('path')
// modify your existing createWindow() function
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
win.loadFile('index.html')
}
// ...
這里使用了兩個Node.js概念:
__dirname
字符串指向當前正在執(zhí)行腳本的路徑 (在本例中,它指向你的項目的根文件夾)。path.join
API 將多個路徑聯(lián)結(jié)在一起,創(chuàng)建一個跨平臺的路徑字符串。我們使用一個相對當前正在執(zhí)行JavaScript文件的路徑,這樣您的相對路徑將在開發(fā)模式和打包模式中都將有效。
此刻,您可能想知道如何為您的應(yīng)用程序添加更多功能。
對于與您的網(wǎng)頁內(nèi)容的任何交互,您想要將腳本添加到您的渲染器進程中。 由于渲染器運行在正常的 Web 環(huán)境中,因此您可以在 index.html
文件關(guān)閉 </body>
標簽之前添加一個 <script>
標簽,來包括您想要的任意腳本:
<script src="./renderer.js"></script>
renderer.js
中包含的代碼可以在接下來使用與前端開發(fā)相同的 JavaScript API 和工具。例如使用 webpack
打包并最小化您的代碼,或者使用 React 來管理您的用戶界面。
完成上述步驟后,您應(yīng)該有一個功能齊全的Electron程序,如下所示:
完整代碼如下:
// main.js
// electron 模塊可以用來控制應(yīng)用的生命周期和創(chuàng)建原生瀏覽窗口
const { app, BrowserWindow } = require('electron')
const path = require('path')
const createWindow = () => {
// 創(chuàng)建瀏覽窗口
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
// 加載 index.html
mainWindow.loadFile('index.html')
// 打開開發(fā)工具
// mainWindow.webContents.openDevTools()
}
// 這段程序?qū)?Electron 結(jié)束初始化
// 和創(chuàng)建瀏覽器窗口的時候調(diào)用
// 部分 API 在 ready 事件觸發(fā)后才能使用。
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
// 在 macOS 系統(tǒng)內(nèi), 如果沒有已開啟的應(yīng)用窗口
// 點擊托盤圖標時通常會重新創(chuàng)建一個新窗口
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
// 除了 macOS 外,當所有窗口都被關(guān)閉的時候退出程序。 因此, 通常
// 對應(yīng)用程序和它們的菜單欄來說應(yīng)該時刻保持激活狀態(tài),
// 直到用戶使用 Cmd + Q 明確退出
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
// 在當前文件中你可以引入所有的主進程代碼
// 也可以拆分成幾個文件,然后用 require 導(dǎo)入。
// preload.js
// 所有的 Node.js API接口 都可以在 preload 進程中被調(diào)用.
// 它擁有與Chrome擴展一樣的沙盒。
window.addEventListener('DOMContentLoaded', () => {
const replaceText = (selector, text) => {
const element = document.getElementById(selector)
if (element) element.innerText = text
}
for (const dependency of ['chrome', 'node', 'electron']) {
replaceText(`${dependency}-version`, process.versions[dependency])
}
})
<!--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'">
<title>你好!</title>
</head>
<body>
<h1>你好!</h1>
我們正在使用 Node.js <span id="node-version"></span>,
Chromium <span id="chrome-version"></span>,
和 Electron <span id="electron-version"></span>.
<!-- 您也可以此進程中運行其他文件 -->
<script src="./renderer.js"></script>
</body>
</html>
DOCS/FIDDLES/QUICK-START (22.0.2)
總結(jié)我們所做的所有步驟:
我們啟動了一個Node.js程序,并將Electron添加為依賴。
我們創(chuàng)建了一個 main.js
腳本來運行我們的主要進程,它控制我們的應(yīng)用程序 并且在 Node.js 環(huán)境中運行。 在此腳本中, 我們使用 Electron 的 app
和 BrowserWindow
模塊來創(chuàng)建一個瀏覽器窗口,在一個單獨的進程(渲染器)中顯示網(wǎng)頁內(nèi)容。
為了訪問渲染器中的Node.js的某些功能,我們在 BrowserWindow
的構(gòu)造函數(shù)上附加了一個預(yù)加載腳本。
最快捷的打包方式是使用 Electron Forge。
npm | Yarn |
|
|
make
命令來創(chuàng)建可分發(fā)的應(yīng)用程序:npm | Yarn |
|
|
Electron-forge 會創(chuàng)建 out
文件夾,您的軟件包將在那里找到:
// Example for macOS
out/
├── out/make/zip/darwin/x64/my-electron-app-darwin-x64-1.0.0.zip
├── ...
└── out/my-electron-app-darwin-x64/my-electron-app.app/Contents/MacOS/my-electron-app
更多建議: