Skip to content

双击 Electron 应用,系统到底启动了什么

DeskLab 的源码只有 HTML、CSS 和 JavaScript,Package 之后的 macOS 应用却达到约 276 MB。体积主要来自 Electron Framework 和 Helper,应用自己的 app.asar 只有约 227 KB。这个对照说明 Electron 没有把页面编译成原生 UI,而是把完整运行时和应用代码一起交付。

运行时由三层组成

提供什么
ChromiumDOM、CSS、页面绘制、V8
Node.js文件、网络、子进程等本地能力
Electronapp、BrowserWindow、IPC、菜单、托盘等桌面接口

操作系统先执行 Contents/MacOS/DeskLab,Main 进程加载 main.js,等待 app ready,创建 BrowserWindow,再导航到 index.html。页面代码随后在独立 Renderer 中运行。

记录真实启动链

Main 入口可以用高精度时钟记录阶段:

js
const { app, BrowserWindow } = require('electron')

const startedAt = process.hrtime.bigint()

function log(event, details = {}) {
  const elapsedMs = Number(process.hrtime.bigint() - startedAt) / 1_000_000
  console.log(JSON.stringify({ event, elapsedMs, pid: process.pid, ...details }))
}

app.whenReady().then(async () => {
  log('when-ready-resolved')
  const win = new BrowserWindow({ webPreferences: { preload: 'preload.js' } })
  win.webContents.once('dom-ready', () => {
    log('renderer-dom-ready', { rendererPid: win.webContents.getOSProcessId() })
  })
  await win.loadFile('index.html')
  log('load-file-resolved')
})

DeskLab 的一次本机观测中,Main PID 和 Renderer PID 不同;app ready、BrowserWindow 创建、DOM ready 和页面加载完成也各有独立时间戳。窗口没有出现时先查 Main 与 app ready;窗口出现但白屏时查 loadFile、导航事件和 Renderer。

app.asar 不是整个应用

macOS 应用目录中至少能看到:

  • Contents/MacOS:操作系统启动的可执行入口。
  • Contents/Frameworks:Electron Framework 与各类 Helper。
  • Contents/Resources:app.asar、图标和应用资源。

只比较源码与 app.asar 会忽略 Chromium、Node.js 和 Helper。评估体积时应比较整个交付产物,并注明 Electron 版本、平台和 CPU 架构。

排查顺序

  1. 确认操作系统实际启动的可执行文件。
  2. 记录 Main 的 app ready 和窗口创建事件。
  3. 记录 webContents 导航、DOM ready 与 Renderer PID。
  4. 打印 process.versions,确认 Electron、Chromium、Node.js 和 modules。
  5. 对照开发态与 Package 产物的入口路径。

Electron 的启动问题只有落到可执行文件、Main、BrowserWindow 和 Renderer 四段链路,才有明确的故障位置。

别急,先让缓存热一下。