01 · 快速开始:第一个 Electron 应用

目标:从零搭一个能跑的窗口应用,理解入口文件、主进程启动、窗口生命周期。 官方对应:创建您的第一个应用程序

实例:Hello Electron

Step 1:初始化项目

mkdir my-electron-app && cd my-electron-app
npm init -y
npm install electron --save-dev

要点:

  • package.json 的 main 字段必须指向入口文件(本例 main.js)
  • author / license / description 打包时是必填项
  • Electron 装在 devDependencies:二进制由打包工具链处理,不算生产依赖
  • pnpm/yarn Berry 用户注意:打包链要求真实 node_modules,pnpm 需设 nodeLinker: hoisted,Yarn Berry 需设 nodeLinker: node-modules

国内加速:镜像配置

npm install electron 卡住不动,是因为二进制从 GitHub Releases 下载。国内设镜像(官方安装指南镜像章节):

项目级 .npmrc(团队共享):

registry=https://registry.npmmirror.com
electron_mirror=https://npmmirror.com/mirrors/electron/
electron_builder_binaries_mirror=https://npmmirror.com/mirrors/electron-builder-binaries/

⚠️ npm 11+ 警告:Unknown project config "electron_mirror"。.npmrc 自定义配置项注入为环境变量的机制将在 npm 下一个大版本移除。当前仍可用,但更稳的做法是 shell 环境变量:

# ~/.zshrc(或 ~/.bashrc)
export ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/
export ELECTRON_BUILDER_BINARIES_MIRROR=https://npmmirror.com/mirrors/electron-builder-binaries/

或一次性环境变量:

ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/ npm install electron --save-dev

要点:

  • 老淘宝源域名(npm.taobao.org / registry.npm.taobao.org)已停用,统一用 npmmirror.com
  • 用 electron-builder 打包时,它还会下载 nsis、winCodeSign 等辅助二进制,需要 electron_builder_binaries_mirror
  • 之前下载失败留下的坏缓存会导致换源后仍报错,先清缓存再装(缓存位置与另一层打包缓存见 07-environment-variables「下载缓存」):
    • macOS:rm -rf ~/Library/Caches/electron
    • Linux:rm -rf ~/.cache/electron
    • Windows:删除 %LOCALAPPDATA%\electron\Cache

常见坑:.npmrc 配了镜像,但直接跑 electron . 时仍慢——因为二进制是惰性下载,直接执行 electron 不经过 npm,.npmrc 不会被注入为 npm_config_electron_mirror。解法:

# 方式 1:手动触发安装(环境变量直接给),之后 electron . 正常用
ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/ node node_modules/electron/install.js
 
# 方式 2:改用 npm script 启动(npm 会注入 .npmrc 配置)
npm start

无镜像时也可走代理:HTTPS_PROXY=http://127.0.0.1:7070 electron .

Step 2:添加入口与页面

index.html:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="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 id="info"></p>
  </body>
  <script src="./renderer.js"></script>
</html>

main.js(完整可运行版):

const { app, BrowserWindow } = require('electron')
 
const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 600
  })
  win.loadFile('index.html')
}
 
app.whenReady().then(() => {
  createWindow()
 
  // macOS:dock 图标点击且无窗口时重建窗口
  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})
 
// Windows/Linux:所有窗口关闭即退出;macOS 保持后台运行
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit()
})

Step 3:运行

package.json 加 script:

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

小技巧:main.js 只写 console.log('Hello from Electron 👋') 也能跑——主进程就是 Node 环境,electron 命令甚至可以当 REPL 用。

关键概念

模块命名规则

  • 可实例化的类:PascalCase(BrowserWindow、Tray、Notification)
  • 单例/函数模块:camelCase(app、ipcRenderer、webContents)
  • TS 项目可用类型化子路径导入:require('electron/main')、require('electron/renderer')、require('electron/common')(仅影响类型检查,不影响运行时)

生命周期时序

npm start → Electron 读取 package.json 的 main
         → 启动主进程(Node 环境)
         → app 触发 ready → 才能创建 BrowserWindow
         → 每个窗口 = 一个独立的渲染进程
  • 用 app.whenReady() 而不是 app.on('ready'),避免监听时机问题(见 electron#21972)
  • process.platform:darwin(macOS)/ win32 / linux,用于平台差异化行为

ESM 支持

Electron 28+ 支持 import 语法的 ECMAScript 模块,详见官方 ESM 指南。教程示例统一用 CommonJS。

可选:VS Code 调试配置

.vscode/launch.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 用 node 调试器启动并暴露 9222 端口,Renderer 用 chrome 调试器 attach 上去;复合任务一键起两个。注意渲染器前几行代码可能因调试器未连上而跳过,可刷新页面或 setTimeout 规避。

练习

  1. 改窗口为 1024×768、title: '我的第一个应用',并设置 win.setMenuBarVisibility(false)
  2. 再加一个 BrowserWindow(两个窗口),观察关闭行为
  3. 用 win.loadURL('https://github.com') 替换 loadFile,加载远程页面

小结

  • Electron 应用 = npm 包,main 字段指定主进程入口
  • 主进程(Node)管生命周期和窗口;渲染进程(Chromium)管 UI
  • 窗口创建必须在 app.whenReady() 之后
  • 下一章:02-process-model — 理解主进程/渲染进程分工与 preload