Electron 桌面应用开发入门指南:从零开始打造 Hello World

Electron 桌面应用开发入门指南:从零开始打造 Hello World

目录


前言

在现代软件开发中,跨平台桌面应用开发一直是一个热门话题。传统的桌面应用开发需要针对不同的操作系统使用不同的技术栈,而 Electron 的出现改变了这一现状。本文将带您从零开始,使用 Electron 构建一个功能完整且美观的 Hello World 应用。

什么是 Electron

核心概念

Electron 是一个使用 Web 技术(JavaScript、HTML 和 CSS)构建跨平台桌面应用的开源框架,由 GitHub 开发并维护。它的核心优势在于:

  • 跨平台:一次编写,在 Windows、macOS 和 Linux 上运行
  • Web 技术栈:使用熟悉的前端技术开发桌面应用
  • 丰富的生态系统:可以使用 npm 上数百万的包
  • 原生能力:可以调用操作系统的原生 API

技术架构

Electron 结合了两个核心组件:

  1. Chromium:提供渲染引擎,负责界面显示
  2. Node.js:提供后端能力,可以访问文件系统、网络等

著名应用案例

  • Visual Studio Code(微软的代码编辑器)
  • Slack(团队协作工具)
  • Discord(语音聊天应用)
  • Atom(GitHub 的文本编辑器)

环境准备

1. Node.js 版本要求

Electron 对 Node.js 版本有要求。本项目使用:

  • Node.js: v20.17.0(LTS 版本)
  • npm: v11.6.0
安装和管理 Node.js

方法一:使用 nvm(Node Version Manager,推荐)

# 安装最新的 LTS 版本
nvm install --lts

# 切换到指定版本
nvm use 20.17.0

# 设置默认版本
nvm alias default 20.17.0

# 查看已安装的版本
nvm ls

方法二:使用 Homebrew(macOS)

# 安装或升级 Node.js
brew install node
# 或
brew upgrade node

2. 验证环境

node -v   # 应该显示 v20.17.0 或更高版本
npm -v    # 应该显示 11.6.0 或更高版本

项目初始化

1. 创建项目目录

mkdir electron-hello-world
cd electron-hello-world

2. 初始化 npm 项目

npm init -y

这会生成一个基础的 package.json 文件。

3. 安装 Electron

npm install --save-dev electron

这将安装最新版本的 Electron(本项目使用 v39.1.1)。

4. 配置 package.json

修改 package.json 文件,添加启动脚本:

{
  "name": "electron-hello-world",
  "version": "1.0.0",
  "main": "main.js",
  "scripts": {
    "start": "electron .",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": "一个简单的 Electron Hello World 应用",
  "devDependencies": {
    "electron": "^39.1.1"
  }
}

关键配置说明

  • "main": "main.js":指定主进程入口文件
  • "start": "electron .":定义启动命令

核心代码详解

1. 主进程(main.js)

主进程是 Electron 应用的核心,负责创建和管理窗口、处理系统事件等。

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

function createWindow () {
  // 创建浏览器窗口
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false
    }
  })

  // 加载 index.html
  mainWindow.loadFile('index.html')

  // 打开开发工具(可选)
  // mainWindow.webContents.openDevTools()
}

// 当 Electron 完成初始化时创建窗口
app.whenReady().then(() => {
  createWindow()

  app.on('activate', function () {
    // 在 macOS 上,当点击 dock 图标并且没有其他窗口打开时,
    // 通常会在应用程序中重新创建一个窗口
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

// 当所有窗口都被关闭时退出应用
app.on('window-all-closed', function () {
  // 在 macOS 上,应用通常会保持活动状态,直到用户明确退出
  if (process.platform !== 'darwin') app.quit()
}
代码详解

1. 引入模块

const { app, BrowserWindow } = require('electron')
  • app:控制应用生命周期
  • BrowserWindow:创建和管理应用窗口

2. 创建窗口函数

const mainWindow = new BrowserWindow({
  width: 800,
  height: 600,
  webPreferences: {
    nodeIntegration: true,      // 允许在渲染进程中使用 Node.js API
    contextIsolation: false     // 关闭上下文隔离(生产环境建议开启)
  }
})

⚠️ 安全提示

  • nodeIntegration: truecontextIsolation: false 在生产环境中存在安全风险
  • 推荐使用 preload 脚本和 IPC 通信来提高安全性

3. 应用生命周期

  • app.whenReady():当 Electron 完成初始化时触发
  • app.on('activate'):macOS 特有,当应用被激活时触发
  • app.on('window-all-closed'):所有窗口关闭时触发

4. 平台差异处理

if (process.platform !== 'darwin') app.quit()

macOS 应用通常在关闭所有窗口后仍保持活动状态,而 Windows 和 Linux 则会退出。

2. 渲染进程(index.html)

渲染进程负责界面显示和用户交互。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Electron Hello World</title>
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
        }
        
        .container {
            text-align: center;
            padding: 40px;
            background: rgba(255, 255, 255, 0.1);
            border-radius: 20px;
            backdrop-filter: blur(10px);
            box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37);
        }
        
        h1 {
            font-size: 3em;
            margin: 0 0 20px 0;
            animation: fadeInDown 1s ease;
        }
        
        p {
            font-size: 1.2em;
            margin: 10px 0;
            animation: fadeInUp 1s ease;
        }
        
        .info {
            margin-top: 30px;
            font-size: 0.9em;
            opacity: 0.8;
        }
        
        @keyframes fadeInDown {
            from {
                opacity: 0;
                transform: translateY(-20px);
            }
            to {
                opacity: 1;
                transform: translateY(0);
            }
        }
        
        @keyframes fadeInUp {
            from {
                opacity: 0;
                transform: translateY(20px);
            }
            to {
                opacity: 1;
                transform: translateY(0);
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>🚀 Hello Electron!</h1>
        <p>欢迎使用 Electron 桌面应用</p>
        <div class="info">
            <p>操作系统: <span id="os-info"></span></p>
            <p>Node.js 版本: <span id="node-version"></span></p>
            <p>Chromium 版本: <span id="chrome-version"></span></p>
            <p>Electron 版本: <span id="electron-version"></span></p>
        </div>
    </div>
    
    <script>
        // 获取操作系统信息
        function getOSInfo() {
            const platform = process.platform;
            const arch = process.arch;
            const osMap = {
                'darwin': 'macOS',
                'win32': 'Windows',
                'linux': 'Linux',
                'freebsd': 'FreeBSD',
                'openbsd': 'OpenBSD',
                'sunos': 'SunOS'
            };
            const osName = osMap[platform] || platform;
            return `${osName} (${arch})`;
        }
        
        // 显示系统和版本信息
        document.getElementById('os-info').innerText = getOSInfo();
        document.getElementById('node-version').innerText = process.versions.node;
        document.getElementById('chrome-version').innerText = process.versions.chrome;
        document.getElementById('electron-version').innerText = process.versions.electron;
    </script>
</body>
</html>
代码详解

1. 系统字体栈

font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;

这个字体栈确保在不同操作系统上使用原生系统字体:

  • -apple-system:macOS San Francisco 字体
  • BlinkMacSystemFont:Chrome on macOS
  • Segoe UI:Windows
  • Roboto:Android

2. 渐变背景

background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);

创建从左上到右下的紫色渐变效果。

3. 毛玻璃效果

background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
  • rgba:半透明白色背景
  • backdrop-filter: blur():背景模糊效果,创造毛玻璃质感

4. 动画效果

@keyframes fadeInDown {
    from {
        opacity: 0;
        transform: translateY(-20px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

标题从上方淡入,内容从下方淡入,提升用户体验。

5. 获取系统信息

function getOSInfo() {
    const platform = process.platform;  // 获取平台标识
    const arch = process.arch;          // 获取架构(x64, arm64 等)
    // ... 映射友好名称
}

通过 Node.js 的 process 对象获取系统信息:

  • process.platform:操作系统平台
  • process.arch:CPU 架构
  • process.versions:各组件版本信息

界面设计与样式

1. 布局策略

使用 Flexbox 实现完美居中:

body {
    display: flex;
    justify-content: center;  /* 水平居中 */
    align-items: center;      /* 垂直居中 */
    height: 100vh;            /* 占满视口高度 */
}

2. 视觉层次

  • 主标题:3em 大字体,吸引注意力
  • 副标题:1.2em,提供说明信息
  • 信息区域:0.9em,较小字体,80% 透明度

3. 色彩方案

  • 主色调:紫色渐变(#667eea → #764ba2)
  • 文字颜色:白色,保证可读性
  • 容器背景:半透明白色 + 毛玻璃效果

4. 交互反馈

虽然这个 Hello World 项目没有交互元素,但可以添加:

button {
    transition: transform 0.2s, box-shadow 0.2s;
}

button:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

button:active {
    transform: translateY(0);
}

运行与调试

1. 启动应用

npm start

或使用 npx(避免 PATH 问题):

npx electron .

2. 开发者工具

main.js 中取消注释以下代码:

mainWindow.webContents.openDevTools()

这将自动打开 Chrome DevTools,用于调试。

3. 热重载

安装 electron-reload 实现热重载:

npm install --save-dev electron-reload

main.js 顶部添加:

require('electron-reload')(__dirname)

4. 调试技巧

主进程调试

# 使用 Node.js inspector
electron --inspect=5858 .

渲染进程调试

  • 使用内置的 Chrome DevTools
  • 可以检查元素、查看控制台、网络请求等

常见问题与解决方案

1. npm 缓存权限问题

问题

Your cache folder contains root-owned files

解决方案

sudo chown -R $(whoami) ~/.npm

2. Electron 下载失败

问题:网络问题导致 Electron 二进制文件下载失败

解决方案:使用镜像源

# 使用淘宝镜像
npm install --save-dev electron --registry=https://registry.npmmirror.com

# 或设置环境变量
export ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"

3. Node 版本不兼容

问题

Unsupported engine for electron@39.1.1: wanted: {"node":">= 12.20.55"}

解决方案

# 使用 nvm 升级 Node.js
nvm install 20
nvm use 20

4. electron 命令找不到

问题

sh: electron: command not found

解决方案

# 方法一:使用 npx
npx electron .

# 方法二:使用相对路径
./node_modules/.bin/electron .

# 方法三:使用 npm start
npm start

5. 安全警告

问题

Electron Security Warning

解决方案

对于生产环境,应该:

const mainWindow = new BrowserWindow({
  webPreferences: {
    nodeIntegration: false,        // 禁用
    contextIsolation: true,        // 启用
    preload: path.join(__dirname, 'preload.js')  // 使用 preload
  }
})

创建 preload.js

const { contextBridge } = require('electron')

contextBridge.exposeInMainWorld('myAPI', {
  platform: process.platform,
  versions: process.versions
})

在渲染进程中使用:

document.getElementById('os-info').innerText = window.myAPI.platform

项目文件结构

electron-hello-world/
├── .gitignore              # Git 忽略文件
├── package.json            # 项目配置
├── package-lock.json       # 依赖锁定文件
├── main.js                 # 主进程入口
├── index.html              # 渲染进程界面
└── node_modules/           # 依赖包(不提交到 Git)

.gitignore 配置

# 依赖
node_modules/

# 日志
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# 操作系统
.DS_Store
Thumbs.db

# IDE
.vscode/
.idea/
*.swp
*.swo
*~

# 构建输出
dist/
build/
out/

# Electron
.npm-cache/

# 环境变量
.env
.env.local

总结与展望

本文收获

通过本教程,您学会了:

  1. ✅ Electron 的基本概念和架构
  2. ✅ 搭建 Electron 开发环境
  3. ✅ 创建主进程和渲染进程
  4. ✅ 使用现代 CSS 创建美观界面
  5. ✅ 获取系统信息并动态显示
  6. ✅ 调试和排查常见问题

进阶方向

1. 添加功能模块

文件操作

const fs = require('fs')
const path = require('path')

// 读取文件
fs.readFile('file.txt', 'utf8', (err, data) => {
  if (err) throw err
  console.log(data)
})

系统托盘

const { Tray, Menu } = require('electron')

let tray = new Tray('/path/to/icon.png')
const contextMenu = Menu.buildFromTemplate([
  { label: '显示', click: () => mainWindow.show() },
  { label: '退出', click: () => app.quit() }
])
tray.setContextMenu(contextMenu)

系统通知

const { Notification } = require('electron')

new Notification({
  title: '通知标题',
  body: '通知内容'
}).show()
2. 主进程与渲染进程通信

主进程

const { ipcMain } = require('electron')

ipcMain.handle('get-data', async () => {
  return { message: 'Hello from main process' }
})

渲染进程

const { ipcRenderer } = require('electron')

const result = await ipcRenderer.invoke('get-data')
console.log(result.message)
3. 打包发布

使用 electron-builder 打包应用:

npm install --save-dev electron-builder

配置 package.json

{
  "build": {
    "appId": "com.example.electron-hello-world",
    "mac": {
      "category": "public.app-category.utilities"
    },
    "win": {
      "target": "nsis"
    },
    "linux": {
      "target": "AppImage"
    }
  }
}

打包命令:

npm run build
4. 自动更新

使用 electron-updater

npm install electron-updater
const { autoUpdater } = require('electron-updater')

app.whenReady().then(() => {
  autoUpdater.checkForUpdatesAndNotify()
})
5. 数据持久化

方案一:使用 localStorage(简单数据)

localStorage.setItem('key', 'value')
const value = localStorage.getItem('key')

方案二:使用 electron-store(推荐)

npm install electron-store
const Store = require('electron-store')
const store = new Store()

store.set('settings', { theme: 'dark' })
const settings = store.get('settings')

方案三:使用 SQLite(复杂数据)

npm install better-sqlite3

学习资源

  • 官方文档:https://www.electronjs.org/docs
  • 中文文档:https://www.electronjs.org/zh/docs
  • Awesome Electron:https://github.com/sindresorhus/awesome-electron
  • 示例项目:https://github.com/electron/electron-quick-start

最佳实践

  1. 安全性优先:在生产环境中启用 contextIsolation
  2. 性能优化:避免在主进程中执行耗时操作
  3. 用户体验:提供加载动画、错误提示
  4. 跨平台测试:在三大平台上都要测试
  5. 代码组织:使用模块化,分离业务逻辑

结语

Electron 为 Web 开发者打开了桌面应用开发的大门。虽然它也有一些缺点(如包体积较大、内存占用较高),但其开发效率和跨平台特性使其成为中小型桌面应用的首选方案。

希望这篇教程能够帮助您快速上手 Electron 开发。从这个 Hello World 开始,您可以逐步添加更多功能,最终开发出功能完整的桌面应用。

记住:每一个伟大的应用都从 Hello World 开始!


附录:完整代码仓库

本项目的完整代码可以在以下位置找到:

/Users/huangwanpeng/Desktop/study/electron-hello-world

欢迎 Star 和 Fork!如有问题,欢迎提 Issue。


作者:[您的名字]
日期:2025年11月9日
版本:v1.0
Electron 版本:39.1.1
Node.js 版本:20.17.0

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序媛夏天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值