Electron 与前端框架 (React, Vue, Angular) 集成教程

Electron 可以与现代前端框架无缝集成,结合各自的优势开发功能丰富的桌面应用。以下是详细的集成指南。

目录

  1. Electron 与 React 集成
  2. Electron 与 Vue 集成
  3. Electron 与 Angular 集成
  4. 通用集成技巧
  5. 常见问题解决

Electron 与 React 集成

方法一:手动集成(推荐)

  1. 创建 React 项目并安装 Electron:
npx create-react-app my-electron-react-app
cd my-electron-react-app
npm install electron electron-builder --save-dev
  1. 添加 Electron 主进程文件 public/electron.js
const { app, BrowserWindow } = require('electron')
const path = require('path')

function createWindow() {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      nodeIntegration: false,
      contextIsolation: true
    }
  })

  // 开发环境加载开发服务器,生产环境加载构建文件
  if (process.env.NODE_ENV === 'development') {
    win.loadURL('http://localhost:3000')
    win.webContents.openDevTools()
  } else {
    win.loadFile(path.join(__dirname, '../build/index.html'))
  }
}

app.whenReady().then(createWindow)

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit()
})

app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
  1. 创建预加载脚本 public/preload.js
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('electronAPI', {
  send: (channel, data) => ipcRenderer.send(channel, data),
  on: (channel, func) => ipcRenderer.on(channel, (event, ...args) => func(...args))
})
  1. 修改 package.json
{
  "main": "public/electron.js",
  "homepage": "./",
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "electron": "electron .",
    "electron-dev": "concurrently \"npm run start\" \"wait-on http://localhost:3000 && npm run electron\"",
    "pack": "electron-builder --dir",
    "dist": "npm run build && electron-builder"
  },
  "build": {
    "appId": "com.example.electronreact",
    "files": [
      "build/**/*",
      "node_modules/**/*",
      "public/electron.js",
      "public/preload.js"
    ],
    "directories": {
      "buildResources": "assets"
    }
  }
}
  1. 安装额外依赖:
npm install concurrently wait-on --save-dev
  1. 启动开发环境:
npm run electron-dev
  1. 构建生产版本:
npm run dist

方法二:使用现成模板

git clone https://github.com/electron-react-boilerplate/electron-react-boilerplate.git
cd electron-react-boilerplate
npm install
npm start

Electron 与 Vue 集成

方法一:手动集成

  1. 创建 Vue 项目并安装 Electron:
npm init vue@latest my-electron-vue-app
cd my-electron-vue-app
npm install
npm install electron electron-builder --save-dev
  1. 添加 Electron 主进程文件 electron/main.js
const { app, BrowserWindow } = require('electron')
const path = require('path')

function createWindow() {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      nodeIntegration: false,
      contextIsolation: true
    }
  })

  if (process.env.NODE_ENV === 'development') {
    win.loadURL('http://localhost:5173')
    win.webContents.openDevTools()
  } else {
    win.loadFile(path.join(__dirname, '../dist/index.html'))
  }
}

app.whenReady().then(createWindow)

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit()
})

app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
  1. 创建预加载脚本 electron/preload.js
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('electronAPI', {
  send: (channel, data) => ipcRenderer.send(channel, data),
  on: (channel, func) => ipcRenderer.on(channel, (event, ...args) => func(...args))
})
  1. 修改 package.json
{
  "main": "electron/main.js",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview",
    "electron": "electron .",
    "electron-dev": "concurrently \"npm run dev\" \"wait-on http://localhost:5173 && npm run electron\"",
    "pack": "electron-builder --dir",
    "dist": "npm run build && electron-builder"
  },
  "build": {
    "appId": "com.example.electronvue",
    "files": [
      "dist/**/*",
      "electron/**/*",
      "node_modules/**/*"
    ]
  }
}
  1. 修改 vite.config.js 确保资源路径正确:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
  base: './'
})
  1. 启动开发环境:
npm run electron-dev
  1. 构建生产版本:
npm run dist

方法二:使用 Vue CLI Plugin

vue create my-electron-vue-app
cd my-electron-vue-app
vue add electron-builder
npm run electron:serve
npm run electron:build

Electron 与 Angular 集成

方法一:手动集成

  1. 创建 Angular 项目并安装 Electron:
ng new my-electron-angular-app
cd my-electron-angular-app
npm install electron electron-builder --save-dev
  1. 添加 Electron 主进程文件 electron/main.js
const { app, BrowserWindow } = require('electron')
const path = require('path')

function createWindow() {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      nodeIntegration: false,
      contextIsolation: true
    }
  })

  if (process.env.NODE_ENV === 'development') {
    win.loadURL('http://localhost:4200')
    win.webContents.openDevTools()
  } else {
    win.loadFile(path.join(__dirname, '../dist/my-electron-angular-app/index.html'))
  }
}

app.whenReady().then(createWindow)

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit()
})

app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
  1. 创建预加载脚本 electron/preload.js
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('electronAPI', {
  send: (channel, data) => ipcRenderer.send(channel, data),
  on: (channel, func) => ipcRenderer.on(channel, (event, ...args) => func(...args))
})
  1. 修改 package.json
{
  "main": "electron/main.js",
  "scripts": {
    "start": "ng serve",
    "build": "ng build",
    "watch": "ng build --watch --configuration development",
    "test": "ng test",
    "electron": "electron .",
    "electron-dev": "concurrently \"npm run start\" \"wait-on http://localhost:4200 && npm run electron\"",
    "pack": "electron-builder --dir",
    "dist": "npm run build && electron-builder"
  },
  "build": {
    "appId": "com.example.electronangular",
    "files": [
      "dist/**/*",
      "electron/**/*",
      "node_modules/**/*"
    ]
  }
}
  1. 修改 angular.json 确保资源路径正确:
{
  "projects": {
    "your-project-name": {
      "architect": {
        "build": {
          "options": {
            "baseHref": "./",
            "outputPath": "dist"
          }
        }
      }
    }
  }
}
  1. 启动开发环境:
npm run electron-dev
  1. 构建生产版本:
npm run dist

方法二:使用 ngx-electron

  1. 安装 ngx-electron:
ng add ngx-electron
  1. 在组件中使用:
import { ElectronService } from 'ngx-electron'

@Component({...})
export class MyComponent {
  constructor(private _electronService: ElectronService) {}

  sendMessage() {
    this._electronService.ipcRenderer.send('message', 'Hello')
  }
}

通用集成技巧

1. 开发环境与生产环境区分

// 在主进程中
const isDev = process.env.NODE_ENV === 'development'

// 在渲染进程中
const isDev = process.env.NODE_ENV === 'development' || 
             (window.process && window.process.env && window.process.env.NODE_ENV === 'development')

2. 共享代码

package.json 中配置别名:

{
  "exports": {
    "./shared": "./src/shared/index.js"
  }
}

3. 热重载

安装 electron-reloader:

npm install electron-reloader --save-dev

在主进程中使用:

try {
  require('electron-reloader')(module)
} catch (_) {}

4. 跨框架组件通信

使用自定义事件:

// 发送事件
window.dispatchEvent(new CustomEvent('electron-event', { detail: data }))

// 接收事件
window.addEventListener('electron-event', (event) => {
  console.log(event.detail)
})

5. 状态管理集成

以 Redux 为例:

// 预加载脚本中暴露 store
contextBridge.exposeInMainWorld('electronStore', {
  getState: () => ipcRenderer.invoke('store-get-state'),
  dispatch: (action) => ipcRenderer.send('store-dispatch', action),
  subscribe: (callback) => {
    ipcRenderer.on('store-state-changed', (event, state) => callback(state))
  }
})

常见问题解决

1. 白屏问题

  • 确保正确加载了 HTML 文件
  • 检查开发者工具中的错误
  • 确认资源路径正确(特别是生产环境)

2. require is not defined

  • 确保 nodeIntegration: falsecontextIsolation: true
  • 使用预加载脚本暴露必要 API

3. 样式不加载

  • 确保 CSS 文件路径正确
  • 检查 CSP 设置
  • 使用绝对路径或 base href

4. 打包后功能异常

  • 确保所有依赖包含在打包文件中
  • 检查文件路径是否正确
  • 测试生产构建而非开发环境

5. 原生模块问题

  • 使用 electron-rebuild 重新编译
  • 检查模块是否兼容 Electron 版本
  • 考虑替代方案或自己实现功能

总结

Electron 与前端框架集成可以充分发挥各自优势:

  • React:组件化开发 + 强大状态管理
  • Vue:简洁语法 + 响应式系统
  • Angular:完整框架 + 依赖注入

关键集成点:

  1. 正确配置主进程和渲染进程
  2. 安全地实现进程间通信
  3. 处理好开发和生产环境的差异
  4. 优化打包配置

选择适合你项目的集成方式,遵循安全最佳实践,就能构建出功能强大、用户体验良好的跨平台桌面应用。









results matching ""

    No results matching ""