Electron 构建你的第一个应用

设置你的项目

初始化npm项目

Electron 应用使用 npm 搭建脚手架,并以 package.json 文件作为入口点。首先创建一个文件夹并在其中使用 npm init 初始化一个 npm 包。

zsh 复制代码
mkdir my-electron-app && cd my-electron-app
npm init

此命令将提示你配置 package.json 中的一些字段。出于本教程的目的,需要遵循一些规则:

  • 入口点应该是 main.js(你很快就会创建该文件)。

  • 作者、许可证和描述可以是任何值,但稍后对于 packaging 是必需的。

然后,将 Electron 安装到应用的 devDependency 中,这是生产中不需要的外部仅开发包依赖的列表。

为什么 Electron 是一个 devDependency?

这可能看起来违反直觉,因为你的生产代码正在运行 Electron API。然而,打包的应用将与 Electron 二进制文件打包在一起,从而无需将其指定为生产依赖。

zsh 复制代码
npm install electron --save-dev

初始化包并安装 Electron 后,你的 package.json 文件应如下所示。你现在还应该有一个包含 Electron 可执行文件的 node_modules 文件夹,以及指定要安装的确切依赖版本的 package-lock.json 锁定文件。

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 文件:

js 复制代码
console.log('Hello from Electron 👋')

由于 Electron 的主进程是 Node.js 运行时,因此你可以使用 electron 命令执行任意 Node.js 代码(你甚至可以将其用作 REPL)。要执行此脚本,请将 electron . 添加到 package.json 的 scripts 字段中的 start 命令中。该命令将告诉 Electron 可执行文件在当前目录中查找主脚本并在开发模式下运行它。

package.json

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"
  }
}
zsh 复制代码
npm run start

你的终端应该打印出 Hello from Electron 👋。恭喜,你已经在 Electron 中执行了第一行代码!接下来,你将学习如何使用 HTML 创建用户界面并将其加载到原生窗口中。

将网页加载到 BrowserWindow 中

Electron 中,每个窗口都显示一个网页,可以从本地 HTML 文件或远程网址加载。对于本示例,你将加载本地文件。首先在项目根文件夹中的 index.html 文件中创建一个准系统网页:

html 复制代码
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <!-- https://web.nodejs.cn/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 文件的内容替换为以下代码。我们将分别解释每个高亮的块。

js 复制代码
const { app, BrowserWindow } = require('electron')

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

  win.loadFile('index.html')
}

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

导入模块

js 复制代码
const { app, BrowserWindow } = require('electron')

在第一行中,我们使用 CommonJS 模块语法导入两个 Electron 模块:

  • app,它控制应用的事件生命周期。

  • BrowserWindow,创建和管理应用窗口。

编写可重用函数来实例化窗口

createWindow() 函数将你的网页加载到新的 BrowserWindow 实例中:

main.js (Lines 3-10)

js 复制代码
const createWindow = () => {  const win = new BrowserWindow({    width: 800,    height: 600  })  win.loadFile('index.html')}

当应用准备就绪时调用你的函数

main.js (Lines 12-14)

复制代码
app.whenReady().then(() => {  createWindow()})

Electron 的许多核心模块都是 Node.js 事件触发器,遵循 Node 的异步事件驱动架构。应用模块就是这些触发器之一。

在 Electron 中,只有在应用模块的 ready 事件被触发后才能创建 BrowserWindows。你可以使用 app.whenReady() API 等待此事件,并在其 promise 履行后调用 createWindow()

此时,运行 Electron 应用的 start 命令应该成功打开一个显示网页的窗口!

你的应用在窗口中显示的每个网页都将在称为渲染器进程(或简称为渲染器)的单独进程中运行。渲染器进程可以访问与典型前端 Web 开发相同的 JavaScript API 和工具,例如使用 webpack 打包和缩小代码或使用 React 构建用户界面。

管理应用的窗口生命周期

应用窗口在每个操作系统上的行为有所不同。如果你希望遵循这些约定,Electron 不会默认强制执行这些约定,而是让你可以选择在应用代码中实现它们。你可以通过监听应用和 BrowserWindow 模块发出的事件来实现基本的窗口约定。

所有窗口关闭后退出应用(Windows 和 Linux)

在 Windows 和 Linux 上,关闭所有窗口通常会完全退出应用。要在你的 Electron 应用中实现此模式,请监听应用模块的 window-all-closed 事件,并在用户不在 macOS 上时调用 app.quit() 退出你的应用。

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

如果没有打开窗口,则打开一个窗口 (macOS)

相比之下,macOS 应用通常即使没有打开任何窗口也会继续运行。在没有可用窗口时激活应用应该会打开一个新窗口。

要实现此功能,请监听应用模块的 activate 事件,并在没有打开 BrowserWindows 的情况下调用现有的 createWindow() 方法。

由于无法在 ready 事件之前创建窗口,因此你应该仅在应用初始化后监听 activate 事件。通过仅监听现有 whenReady() 回调中的激活事件来执行此操作。

js 复制代码
app.whenReady().then(() => {  
	createWindow()  
	app.on('activate', () => {    
	if (BrowserWindow.getAllWindows().length === 0) createWindow()  
	})
})

最终的起始代码

main.js

js 复制代码
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()
  }
})

index.html

html 复制代码
<!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>
相关推荐
枫叶梨花4 小时前
Electrobun透明窗口在Windows上的输入穿透排查
前端·electron·bun
xiaoyan20157 小时前
2026最新款Electron41+React19+AntDesign电脑端后台管理系统Exe
react.js·electron·vite
会周易的程序员2 天前
告别 matiec 与 Docker:aiDgePLC Editor 全面拥抱 STVM 字节码编译
物联网·网关·electron·软plc·iec61131·stvm·open plc
Flynt4 天前
Chrome 修了个零日漏洞,你的 VS Code 和 Cursor 可能还在裸奔
安全·electron·visual studio code
星辰徐哥4 天前
鸿蒙PC平台 Gnote 笔记应用适配实战:从 Linux 到 鸿蒙PC 的 Electron 迁移
linux·笔记·electron·harmonyos·gnote
不可能片场5 天前
nohup 之后进程还是死了:GUI 子进程的存活陷阱
前端·electron
工边页字6 天前
Electron应用的8种防护方式
前端·javascript·electron
不可能片场7 天前
resources/app 为何能覆盖 app.asar
前端·electron
不可能片场7 天前
Electron 子进程退化成 node 的 env 陷阱
前端·electron