# my-electron-app **Repository Path**: zhao-jingtao-l_admin/my-electron-app ## Basic Information - **Project Name**: my-electron-app - **Description**: Electron 应用基于 npm 搭建 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-10-15 - **Last Updated**: 2024-12-14 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 创建您的第一个应用程序 教程目录 这是 Electron 教程的**第二部分**。 1. [基本要求](https://www.electronjs.org/zh/docs/latest/tutorial/tutorial-prerequisites) 2. **[创建您的第一个应用程序](https://www.electronjs.org/zh/docs/latest/tutorial/tutorial-first-app)** 3. [使用预加载脚本](https://www.electronjs.org/zh/docs/latest/tutorial/tutorial-preload) 4. [添加功能](https://www.electronjs.org/zh/docs/latest/tutorial/tutorial-adding-features) 5. [打包您的应用程序](https://www.electronjs.org/zh/docs/latest/tutorial/打包教程) 6. [发布和更新](https://www.electronjs.org/zh/docs/latest/tutorial/推送更新教程) ## 学习目标 在本节,您会学习如何创建您的 Electron 项目,并且编写一个简单的入门程序。 到了本节末尾,您应该能够在终端开发环境运行一个 Electron 应用。 ## 创建项目 避免使用 WSL 如果您使用的是Windows系统,在本教程中请不要使用 [Windows Subsystem for Linux](https://learn.microsoft.com/en-us/windows/wsl/about#what-is-wsl-2) (WSL),否则您在尝试运行应用时可能会遇到问题。 ### 初始化 npm 项目 Electron 应用基于 npm 搭建,以 package.json 文件作为入口点。 首先创建一个文件夹,然后在其中执行 `npm init` 初始化项目。 - npm - Yarn ```sh mkdir my-electron-app && cd my-electron-app npm init ``` 这条命令会帮您配置 package.json 中的一些字段。 为本教程的目的,有几条规则需要遵循: - *入口点* 应当是 `main.js` (您很快就会创建它) - *author*、*license* 和 _description_可为任意值,但对于 [应用打包](https://www.electronjs.org/zh/docs/latest/tutorial/打包教程) 是必填项。 然后,将 Electron 安装为您项目的 **devDependencies**,即仅在开发环境需要的额外依赖。 为什么 Electron 是 devDependency? 您的应用需要运行 Electron API,因此这听上去可能有点反直觉。 实际上,打包后的应用本身会包含 Electron 的二进制文件,因此不需要将 Electron 作为生产环境依赖。 - npm - Yarn ```sh npm install electron --save-dev ``` 在初始化并且安装完 Electron 之后,您的 package.json 应该长下面这样。 文件夹中会出现一个 `node_modules` 文件夹,其中包含了 Electron 可执行文件;还有一个 `package-lock.json` 文件,指定了各个依赖的确切版本。 package.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 失败,请参考我们的 [安装指导](https://www.electronjs.org/zh/docs/latest/tutorial/installation) 文档,了解有关下载镜像、代理和故障排除步骤的说明。 ### 添加 .gitignore 文件 [`.gitignore`](https://git-scm.com/docs/gitignore) 文件可以指定哪些文件和目录应该在Git中不被跟踪。 建议您复制一份 [GitHub 的 Node.js gitignore 模板](https://github.com/github/gitignore/blob/main/Node.gitignore) 到您项目的根目录,以避免将 `node_modules` 文件夹提交到版本控制系统中。 ## 运行 Electron 应用 :::延伸阅读 参阅 [Electron 进程模型(process model)](https://www.electronjs.org/zh/docs/latest/tutorial/process-model) 相关文档来了解 Electron 的进程之间是如何协作的。 ::: 您在 package.json 中指定的 [`main`](https://docs.npmjs.com/cli/v7/configuring-npm/package-json#main) 文件是 Electron 应用的入口。 这个文件控制 **主程序 (main process)**,它运行在 Node.js 环境里,负责控制您应用的生命周期、显示原生界面、执行特殊操作并管理渲染器进程 (renderer processes),稍后会详细介绍。 在继续编写您的 Electron 应用之前,您将使用一个小小的脚本来确保主进程入口点已经配置正确。 在根目录的 `main.js` 文件中写一行代码: main.js ```js console.log('Hello from Electron 👋') ``` 由于 Electron 的主进程是一个 Node.js 运行时,您可以使用 `electron` 命令执行任意的 Node.js 代码 (甚至可以将其作为 [REPL](https://www.electronjs.org/zh/docs/latest/tutorial/repl) 使用)。 要执行这个脚本,需要在 package.json 的 [`scripts`](https://docs.npmjs.com/cli/v7/using-npm/scripts) 字段中添加一个 `start` 命令,内容为 `electron .` 。 这个命令会告诉 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" } } ``` - npm - Yarn ```sh npm run start ``` 您的终端应该会输出 `欢迎来到 Electron 👋`。 恭喜,您已经在 Electron 中执行了您的第一行代码! 接下来,您会学习如何用 HTML 创建用户界面,并将它们装载到原生窗口中。 ## 将网页装载到 BrowserWindow 在 Electron 中,每个窗口展示一个页面,后者可以来自本地的 HTML,也可以来自远程 URL。 在本例中,您将会装载本地的文件。 在您项目的根目录中创建一个 `index.html` 文件,并写入下面的内容: index.html ```html Hello from Electron renderer!

Hello from Electron renderer!

👋

``` 现在您有了一个网页,您可以将其加载到一个 Electron 的 [BrowserWindow](https://www.electronjs.org/zh/docs/latest/api/browser-window) 上了。 将 `main.js` 中的内容替换成下列代码。 我们马上会逐行解释。 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() }) ``` ### 导入模块 main.js (Line 1) ```js const { app, BrowserWindow } = require('electron') ``` 在第一行中,我们使用 CommonJS 语法导入了两个 Electron 模块: - [app](https://www.electronjs.org/zh/docs/latest/api/app),它着您应用程序的事件生命周期。 - [BrowserWindow](https://www.electronjs.org/zh/docs/latest/api/browser-window),它负责创建和管理应用窗口。
模块名的大小写规范
类型化导入别名
Electron 中的 ES 模块 Electron 28 起,Electron 支持[ECMAScript 模块](https://nodejs.org/api/esm.html)(即使用 `import` 加载模块)。 您可以在我们的 [ESM 指南](https://www.electronjs.org/zh/docs/latest/tutorial/esm) 中找到有关 Electron 中 ESM 状态以及如何在我们的应用程序中使用它们的更多信息。 ### 将可复用的函数写入实例化窗口 `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) ```js app.whenReady().then(() => { createWindow() }) ``` Electron 的许多核心模块都是 Node.js 的[事件触发器](https://nodejs.org/api/events.html#events),遵循 Node.js 的异步事件驱动架构。 app 模块就是其中一个。 在 Electron 中,只有在 app 模块的 [`ready`](https://www.electronjs.org/zh/docs/latest/api/app#event-ready) 事件触发后才能创建 BrowserWindows 实例。 您可以通过使用 [`app.whenReady()`](https://www.electronjs.org/zh/docs/latest/api/app#appwhenready) API 来监听此事件,并在其成功后调用 `createWindow()` 方法。 info 通常我们使用触发器的 `.on` 函数来监听 Node.js 事件。 ```diff + app.on('ready', () => { - app.whenReady().then(() => { createWindow() }) ``` 但是 Electron 暴露了 `app.whenReady()` 方法,作为其 `ready` 事件的专用监听器,这样可以避免直接监听 .on 事件带来的一些问题。 参见 [electron/electron#21972](https://github.com/electron/electron/pull/21972) 。 此时,运行 `start` 命令应该能成功地打开一个包含您网页内容的窗口! 您应用中的每个页面都在一个单独的进程中运行,我们称这些进程为 **渲染器 (\*renderer\*)** 。 渲染进程使用与常规Web开发相同的JavaScript API和工具,例如使用 [webpack](https://webpack.js.org/)来打包和压缩您的代码,或使用 [React](https://reactjs.org/) 构建用户界面。 ## 管理应用的窗口生命周期 应用窗口在不同操作系统中的行为也不同。 Electron 允许您自行实现这些行为来遵循操作系统的规范,而不是采用默认的强制执行。 您可以通过监听 app 和 BrowserWindow 模组的事件,自行实现基础的应用窗口规范。 针对特定进程的控制流 通过检查 Node.js 的 [`process.platform`](https://nodejs.org/api/process.html#process_process_platform) 变量,您可以针对特定平台运行特定代码。 请注意,Electron 目前只支持三个平台:`win32` (Windows), `linux` (Linux) 和 `darwin` (macOS) 。 ### 关闭所有窗口时退出应用 (Windows & Linux) 在 Windows 和 Linux 上,我们通常希望在关闭一个应用的所有窗口后让它退出。 要在您的Electron应用中实现这一点,您可以监听 app 模块的 [`window-all-closed`](https://www.electronjs.org/zh/docs/latest/api/app#event-window-all-closed) 事件,并调用 [`app.quit()`](https://www.electronjs.org/zh/docs/latest/api/app#appquit) 来退出您的应用程序。此方法不适用于 macOS。 ```js app.on('window-all-closed', () => { if (process.platform !== 'darwin') app.quit() }) ``` ### 如果没有窗口打开则打开一个窗口 (macOS) 与前二者相比,即使没有打开任何窗口,macOS 应用通常也会继续运行。 在没有窗口可用时调用 app 会打开一个新窗口。 为了实现这一特性,可以监听模组的 [`activate`](https://www.electronjs.org/zh/docs/latest/api/app#event-activate-macos) 事件,如果没有任何活动的 BrowserWindow,调用 `createWindow()` 方法新建一个。 因为窗口无法在 `ready` 事件前创建,你应当在你的应用初始化后仅监听 `activate` 事件。 要实现这个,仅监听 `whenReady()` 回调即可。 ```js app.whenReady().then(() => { createWindow() app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) createWindow() }) }) ``` ## 完整实现代码 [docs/fiddles/tutorial-first-app (32.1.2)](https://github.com/electron/electron/tree/v32.1.2/docs/fiddles/tutorial-first-app)[Open in Fiddle](https://fiddle.electronjs.org/launch?target=electron/v32.1.2/docs/fiddles/tutorial-first-app) - main.js - index.html ```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() } }) ``` ## 可选:使用 VS Code 调试 如果您希望使用 VS Code 调试您的程序,您需要让 VS Code 监听主进程 (main process) 和渲染器进程 (renderer process) 。 下面为您提供了一个简单的配置文件。 请在根目录新建一个 `.vscode` 文件夹,然后在其中新建一个 launch.json 配置文件并填写如下内容。 .vscode/launch.json ```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" } ] } ``` 保存后,当您选择侧边栏的 “运行和调试”,将会出现一个 "Main + renderer" 选项。然后您便可设置断点,并跟踪主进程和渲染器进程中的所有变量。 上文中我们在 `launch.json` 所做的其实是创建三个配置项: - `Main` 用来运行主程序,并且暴露出 9222 端口用于远程调试 (`--remote-debugging-port=9222`) 。 我们将把调试器绑定到那个端口来调试 `renderer` 。 因为主进程是 Node.js 进程,类型被设置为 `node`。 - `Renderer` 用来调试渲染器进程。 因为后者是由主进程创建的,我们要把它 “绑定” 到主进程上 ()`"request": "attach"`,而不是创建一个新的。 渲染器是 web 进程,因此要选择 `chrome` 调试器。 - `Main + renderer` 是一个 [复合任务](https://code.visualstudio.com/Docs/editor/tasks#_compound-tasks),可以同时执行上述任务。 注意事项 由于我们要将进程绑定到 `Renderer` 任务,您应用中的前几行代码可能会被跳过,因为调试器 (Debugger) 在执行代码之前没有足够的时间进行连接。 在开发环境中,您可以通过刷新页面或者使用 setTimeout 延迟运行代码,来避开这个问题。 延伸阅读 如果您希望深挖调试步骤,可以查看以下指南: - [调试应用](https://www.electronjs.org/zh/docs/latest/tutorial/application-debugging) - [DevTools 扩展](https://www.electronjs.org/zh/docs/latest/tutorial/devtools-extension)