第35章 跨平台桌面开发

Chapter-35 - 跨平台桌面开发

35.1 Electron

35.1.1 Electron 架构:主进程 + 渲染进程

Electron 使用 Chromium + Node.js,分为:

  • 主进程(Main Process):Node.js 环境,管理窗口、系统操作
  • 渲染进程(Renderer Process):Chromium 环境,运行 React 应用

35.1.2 React + Electron 项目搭建

1
2
3
4
# npm create electron-vite@latest:调用 npm 执行 electron-vite 脚手架工具
# my-app:项目名称(会创建一个同名文件夹)
# electron-vite 集成了 Vite + Electron,比纯 Electron 配置少很多
npm create electron-vite@latest my-app

35.1.3 IPC 通信:主进程与渲染进程数据交换

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// 主进程(main/index.ts)
import { app, ipcMain } from 'electron'

ipcMain.handle('get-app-version', () => {
  return app.getVersion()
})

ipcMain.handle('open-file-dialog', async () => {
  const { dialog } = require('electron')
  const result = await dialog.showOpenDialog({ properties: ['openFile'] })
  return result.filePaths
})
1
2
3
4
5
6
7
// 渲染进程( preload.cjs,用于安全暴露 API)
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('electronAPI', {
  getAppVersion: () => ipcRenderer.invoke('get-app-version'),
  openFileDialog: () => ipcRenderer.invoke('open-file-dialog')
})
1
2
// React 组件中调用
const version = await window.electronAPI.getAppVersion()

35.1.4 electron-builder 打包发布

1
npm install -D electron-builder
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
// electron-builder.json
{
  // 应用唯一标识符,格式通常为 com.公司名.产品名,用于系统安装和卸载
  "appId": "com.myapp.desktop",
  // 打包后显示的应用名称(即开始菜单/程序列表中的名字)
  "productName": "MyApp",
  // 打包输出目录,"release" 文件夹下会生成各平台的安装包
  "directories": { "output": "release" },
  // 需要打包进应用的文件或目录(** 通配符表示递归匹配)
  // 此处将 Vite 构建产物 dist 目录下的所有文件打包
  "files": ["dist/**/*"],
  // Windows 平台打包配置
  // target 指定打包格式:nsis = 安装向导格式(.exe),portable = 单文件便携版
  // 可选值还有:portable、appx、msi 等
  "win": { "target": ["nsis"] },
  // macOS 平台打包配置
  // target 可选:dmg(磁盘镜像)、pkg(安装包)、zip(压缩包)
  "mac": { "target": ["dmg"] },
  // Linux 平台打包配置
  // target 可选:AppImage(通用可执行格式)、deb(Debian/Ubuntu)、rpm(Fedora/RHEL)、tar.gz
  "linux": { "target": ["AppImage"] }
}

35.2 Tauri

35.2.1 Tauri 的优势:体积小、安全、Rust 后端

Tauri 用 Rust 替代 Node.js 作为后端,产物极小(~3MB vs Electron 的 100MB+)。包体积小的代价是:Node.js 生态不可用,系统级 API 需要额外配置。

35.2.2 React + Tauri 项目搭建

1
2
3
4
5
6
7
8
9
# npm create tauri-app@latest:调用 npm 执行 tauri-app 脚手架工具
# my-app:项目名称
# -- --template react-ts:两个 -- 的含义:
#   第一个 --:npm create 的标准分隔符,告诉 npm 后面是给 tauri-app 的参数
#   第二个 --:tauri-app 的参数分隔符
#   template react-ts:指定使用 React + TypeScript 模板
npm create tauri-app@latest my-app -- --template react-ts
cd my-app
npm run tauri dev

35.2.3 Tauri 命令调用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// src-tauri/src/lib.rs
#[tauri::command]
fn greet(name: &str) -> String {
    format!("Hello, {} from Rust! 🦀", name)
}

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .invoke_handler(tauri::generate_handler![greet])
        .run(tauri::generate_context!())
        .expect("启动 Tauri 出错了");
}
1
2
3
4
5
// React 组件中调用
import { invoke } from '@tauri-apps/api/tauri'

const greeting = await invoke('greet', { name: 'World' })
console.log(greeting) // "Hello, World from Rust! 🦀"

35.2.4 Tauri 权限配置(Tauri 2.x 新增)

Tauri 2.x 引入了权限系统,访问系统 API 需要声明权限:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// src-tauri/capabilities/default.json
{
  "identifier": "default",           // 权限配置的唯一名称,"default" 表示这是默认权限集
  "description": "默认权限",          // 描述,供开发者和 Tauri 工具链使用,不影响实际行为
  "windows": ["main"],               // 该权限适用的窗口名称(与 src-tauri-tauri.conf.json 中窗口配置对应)
  "permissions": [                   // Tauri 2.x 权限白名单,必须显式声明才能调用对应系统 API
    "core:default",                   // 核心 API(窗口管理、应用信息等基础能力)
    "dialog:default",                // 对话框 API(打开/保存文件、弹出提示框等)
    "fs:default",                     // 文件系统 API(默认已包含常见目录的读写权限,可满足大多数场景)
    "shell:default"                   // Shell API(打开外部链接、启动系统应用等)
  ]
}

35.3 Tauri vs Electron

35.3.1 体积与性能对比

对比ElectronTauri
产物大小~100MB+~3-10MB
启动速度慢(Chromium 启动开销大)
内存占用
Node.js 生态✅ 完全支持❌ 不可用
系统 API通过 Node 模块需 Rust 插件或权限配置
社区成熟度非常成熟(2013年起)较新(Tauri 2.0 于 2024 年)

35.3.2 安全性对比

  • Electron:Node.js 完全可用,安全风险较高,需手动沙箱化
  • Tauri:默认禁用 Node.js,通过权限系统白名单访问系统资源,更安全

35.3.3 选型建议

  • 需要小体积、高安全、快速启动 → Tauri(推荐新项目)
  • 需要复杂 Node.js 生态、Native 模块支持 → Electron
  • 已经在用 Electron 的老项目 → 没必要迁移,Tauri 的学习曲线也值得考虑

本章小结

本章我们学习了 React 的跨平台桌面开发:

  • Electron:成熟稳定,Node.js 生态丰富,包体积约 100MB+
  • Tauri:轻量安全,Rust 后端,包体积仅 3-10MB
  • IPC 通信:Electron 用 ipcMain/ipcRenderer,Tauri 用 invoke()
  • Tauri 2.x:新增权限系统,系统 API 访问需声明权限

选 Electron 还是 Tauri?一句话:新项目优先 Tauri,老项目别折腾迁移。下一章我们将学习 React 工程化与架构!🏗️