Electron 快速入門

2023-02-16 17:13 更新

本指南將會通過使用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)。

創(chuàng)建你的應(yīng)用程序?

使用腳手架創(chuàng)建?

Electron 應(yīng)用程序遵循與其他 Node.js 項目相同的結(jié)構(gòu)。 首先創(chuàng)建一個文件夾并初始化 npm 包。

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

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
npm install --save-dev electron
yarn add --dev electron

注意:如果您在安裝 Electron 時遇到任何問題,請參見 安裝指導(dǎo) 指南。

最后,您希望能夠執(zhí)行 Electron 如下所示,在您的 package.json配置文件中的scripts字段下增加一條start命令:

{
  "scripts": {
    "start": "electron ."
  }
}

start命令能讓您在開發(fā)模式下打開您的應(yīng)用

 npm  Yarn
npm start
yarn start
# couldn't auto-convert command

注意:此腳本將告訴 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?中添加任何代碼。

創(chuàng)建頁面?

在可以為我們的應(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)運行代碼。

關(guān)閉所有窗口時退出應(yīng)用 (Windows & Linux)?

在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()
})

如果沒有窗口打開則打開一個窗口 (macOS)?

當 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)功能齊全!

通過預(yù)加載腳本從渲染器訪問Node.js。?

現(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ā)模式和打包模式中都將有效。

額外:將功能添加到您的網(wǎng)頁內(nèi)容?

此刻,您可能想知道如何為您的應(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)

Open in Fiddle

總結(jié)我們所做的所有步驟:

  • 我們啟動了一個Node.js程序,并將Electron添加為依賴。

  • 我們創(chuàng)建了一個 main.js 腳本來運行我們的主要進程,它控制我們的應(yīng)用程序 并且在 Node.js 環(huán)境中運行。 在此腳本中, 我們使用 Electron 的 appBrowserWindow 模塊來創(chuàng)建一個瀏覽器窗口,在一個單獨的進程(渲染器)中顯示網(wǎng)頁內(nèi)容。

  • 為了訪問渲染器中的Node.js的某些功能,我們在 BrowserWindow 的構(gòu)造函數(shù)上附加了一個預(yù)加載腳本。

打包并分發(fā)您的應(yīng)用程序?

最快捷的打包方式是使用 Electron Forge。

  1. 將 Electron Forge 添加到您應(yīng)用的開發(fā)依賴中,并使用其"import"命令設(shè)置 Forge 的腳手架:
  2.  npm  Yarn
    npm install --save-dev @electron-forge/cli
    npx electron-forge import
    
    ? Checking your system
    ? Initializing Git Repository
    ? Writing modified package.json file
    ? Installing dependencies
    ? Writing modified package.json file
    ? Fixing .gitignore
    
    We have ATTEMPTED to convert your app to be in a format that electron-forge understands.
    
    Thanks for using "electron-forge"!!!
    yarn add --dev @electron-forge/cli
    npx electron-forge import
    
    ? Checking your system
    ? Initializing Git Repository
    ? Writing modified package.json file
    ? Installing dependencies
    ? Writing modified package.json file
    ? Fixing .gitignore
    
    We have ATTEMPTED to convert your app to be in a format that electron-forge understands.
    
    Thanks for using "electron-forge"!!!
  3. 使用 Forge 的 make 命令來創(chuàng)建可分發(fā)的應(yīng)用程序:
  4.  npm Yarn 
    npm run make
    
    > my-electron-app@1.0.0 make /my-electron-app
    > electron-forge make
    
    ? Checking your system
    ? Resolving Forge Config
    We need to package your application before we can make it
    ? Preparing to Package Application for arch: x64
    ? Preparing native dependencies
    ? Packaging Application
    Making for the following targets: zip
    ? Making for target: zip - On platform: darwin - For arch: x64
    yarn run make
    
    > my-electron-app@1.0.0 make /my-electron-app
    > electron-forge make
    
    ? Checking your system
    ? Resolving Forge Config
    We need to package your application before we can make it
    ? Preparing to Package Application for arch: x64
    ? Preparing native dependencies
    ? Packaging Application
    Making for the following targets: zip
    ? Making for target: zip - On platform: darwin - For arch: x64

    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


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號