文章目录
-
- Electron开发的核心功能要点总结
- [Electron api-主进程、渲染进程及通信补充](#Electron api-主进程、渲染进程及通信补充)
-
- 一、主进程的核心作用(附实例)
-
- [1. 管理应用生命周期](#1. 管理应用生命周期)
- [2. 创建与管理窗口(渲染进程载体)](#2. 创建与管理窗口(渲染进程载体))
- [3. 访问系统资源(渲染进程无权直接访问)](#3. 访问系统资源(渲染进程无权直接访问))
- [4. 作为进程间通信(IPC)的中介](#4. 作为进程间通信(IPC)的中介)
- [5. 管理菜单、托盘、对话框等系统级UI](#5. 管理菜单、托盘、对话框等系统级UI)
- 二、渲染进程如何从环境变量获取API参数配置?
-
- 详细步骤与实例:
-
- [1. 主进程准备环境变量并监听IPC请求](#1. 主进程准备环境变量并监听IPC请求)
- [2. 预加载脚本(preload.js)暴露IPC接口](#2. 预加载脚本(preload.js)暴露IPC接口)
- [3. 渲染进程调用接口获取环境变量](#3. 渲染进程调用接口获取环境变量)
- [4. 如何设置环境变量?](#4. 如何设置环境变量?)
- 三、关键注意事项
- 总结
Electron开发的核心功能要点总结
一、项目创建
核心要点:
- Electron基于Node.js,需通过npm管理依赖
- 推荐使用脚手架简化创建流程(如
electron-forge
、electron-vite
)
实例(手动创建):
bash
# 1. 初始化项目
mkdir electron-demo && cd electron-demo
npm init -y
# 2. 安装Electron(开发依赖)
npm install electron --save-dev
# 3. 配置package.json(关键字段)
{
"name": "electron-demo",
"version": "1.0.0",
"main": "main.js", // 主进程入口文件
"scripts": {
"start": "electron ." // 启动命令
}
}
注意事项:
- 确保Node.js版本≥14(Electron对Node版本有最低要求)
- 国内环境建议配置npm镜像(如
npm config set electron_mirror https://npmmirror.com/mirrors/electron/
)
二、配置文件设置
核心要点:
- 主配置文件:
package.json
(指定主进程入口、脚本命令等) - 主进程窗口配置:通过
BrowserWindow
参数定义窗口属性
实例(主进程窗口配置):
javascript
// main.js(主进程)
const { app, BrowserWindow } = require('electron')
function createWindow() {
// 创建浏览器窗口
const mainWindow = new BrowserWindow({
width: 800, // 窗口宽度
height: 600, // 窗口高度
title: "Electron示例", // 窗口标题
webPreferences: {
nodeIntegration: false, // 禁用Node.js集成(安全建议)
contextIsolation: true, // 启用上下文隔离(默认开启,安全隔离)
preload: path.join(__dirname, 'preload.js') // 预加载脚本(进程通信桥梁)
}
})
// 加载渲染进程页面
mainWindow.loadFile('index.html')
// 打开开发者工具
mainWindow.webContents.openDevTools()
}
注意事项:
nodeIntegration: true
存在安全风险(允许渲染进程直接访问Node API),建议禁用preload.js
是安全暴露API给渲染进程的唯一推荐方式
三、主进程与渲染进程
核心概念:
-
主进程:
- 运行在Node.js环境,一个应用只有一个主进程
- 负责管理窗口、菜单、系统资源(如文件、网络)等
- 入口:
package.json
中main
字段指定的文件(如main.js
)
-
渲染进程:
- 每个窗口对应一个渲染进程,运行在Chromium环境
- 负责页面渲染(HTML/CSS/JS),可使用前端框架(Vue/React等)
- 入口:通过
mainWindow.loadFile('index.html')
加载的HTML文件
实例(渲染进程页面):
html
<!-- index.html(渲染进程) -->
<!DOCTYPE html>
<html>
<body>
<h1>Hello Electron!</h1>
<button id="sendBtn">发送消息给主进程</button>
<script src="renderer.js"></script> <!-- 渲染进程脚本 -->
</body>
</html>
注意事项:
- 主进程不能直接操作DOM,DOM操作必须在渲染进程中完成
- 渲染进程默认无法访问Node API,需通过
preload.js
安全暴露
四、主进程与渲染进程交互
核心方式:
- IPC(Inter-Process Communication) :通过
ipcMain
(主进程)和ipcRenderer
(渲染进程)实现
实例1:渲染进程发送消息→主进程接收并回复
javascript
// 1. 主进程(main.js)
const { ipcMain } = require('electron')
// 监听渲染进程消息
ipcMain.handle('renderer-msg', async (event, arg) => {
console.log('主进程收到:', arg) // 输出:"Hello 主进程"
return '主进程已收到消息' // 回复渲染进程
})
javascript
// 2. 预加载脚本(preload.js):暴露IPC API给渲染进程
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('electronAPI', {
sendMsg: (msg) => ipcRenderer.invoke('renderer-msg', msg)
})
javascript
// 3. 渲染进程(renderer.js)
document.getElementById('sendBtn').addEventListener('click', async () => {
const response = await window.electronAPI.sendMsg('Hello 主进程')
console.log('渲染进程收到回复:', response) // 输出:"主进程已收到消息"
})
实例2:主进程主动发送消息→渲染进程
javascript
// 1. 主进程(main.js):向渲染进程发送消息
mainWindow.webContents.send('main-msg', '来自主进程的通知')
javascript
// 2. 预加载脚本(preload.js):暴露监听方法
contextBridge.exposeInMainWorld('electronAPI', {
onMainMsg: (callback) => ipcRenderer.on('main-msg', (event, arg) => callback(arg))
})
javascript
// 3. 渲染进程(renderer.js):监听主进程消息
window.electronAPI.onMainMsg((msg) => {
console.log('渲染进程收到主进程消息:', msg) // 输出:"来自主进程的通知"
})
注意事项:
- 禁止在渲染进程中处理敏感操作(如文件写入、系统命令),应交给主进程处理
- 使用
contextBridge
暴露API时,避免直接暴露ipcRenderer
(防止滥用) - 消息命名建议使用业务前缀(如
file:save
、window:minimize
),避免冲突
五、组件交互(渲染进程内部)
核心要点:
- 渲染进程内的组件交互与普通前端项目一致,依赖前端框架的状态管理机制
实例(Vue组件交互):
vue
<!-- 父组件 -->
<template>
<ChildComponent @child-event="handleChildEvent" />
</template>
<script>
export default {
methods: {
handleChildEvent(data) {
console.log('父组件收到子组件数据:', data)
}
}
}
</script>
<!-- 子组件 -->
<template>
<button @click="sendToParent">发送数据给父组件</button>
</template>
<script>
export default {
methods: {
sendToParent() {
this.$emit('child-event', '来自子组件的数据')
}
}
}
</script>
注意事项:
- 渲染进程内的组件通信与Electron无关,遵循前端框架自身规范
- 若需跨窗口(不同渲染进程)通信,需通过主进程转发(主进程作为中介)
六、进程挂载(应用初始化)
核心要点:
- 主进程挂载:应用启动时初始化窗口、配置、监听事件
- 渲染进程挂载:页面加载时初始化DOM、绑定事件、调用API
实例(主进程初始化流程):
javascript
// main.js
const { app, BrowserWindow } = require('electron')
const path = require('path')
// 应用就绪后创建窗口
app.whenReady().then(() => {
createWindow() // 创建主窗口
// 监听应用激活事件(macOS特有)
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
// 所有窗口关闭时退出应用(Windows/Linux)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
注意事项:
- 窗口创建必须在
app.whenReady()
回调中执行(确保应用初始化完成) - macOS应用关闭所有窗口后不会退出,需监听
activate
事件重新创建窗口
七、其他关键注意事项
-
安全配置:
-
启用
contextIsolation: true
(默认开启),隔离主进程与渲染进程上下文 -
设置Content-Security-Policy(CSP)防止XSS攻击:
html<meta http-equiv="Content-Security-Policy" content="default-src 'self'">
-
-
调试技巧:
- 主进程调试:
npm start --inspect=5858
,通过chrome://inspect
连接 - 渲染进程调试:
mainWindow.webContents.openDevTools()
打开开发者工具
- 主进程调试:
-
打包发布:
- 使用
electron-builder
或electron-packager
,配置package.json
的build
字段指定图标、平台等 - 示例:
npm install electron-builder --save-dev
,添加脚本"package": "electron-builder"
- 使用
通过以上要点,可快速掌握Electron的核心开发流程,重点关注主进程与渲染进程的职责划分及安全通信方式。
在Electron开发中,渲染进程获取环境变量、主进程的角色定位是核心问题,涉及安全隔离与进程职责划分。下面详细说明并举例:
Electron api-主进程、渲染进程及通信补充
一、主进程的核心作用(附实例)
主进程是Electron应用的"大脑",运行在Node.js环境中,负责管理应用生命周期、系统资源交互、窗口创建等核心功能。一个应用只有一个主进程,其核心作用如下:
1. 管理应用生命周期
控制应用的启动、退出、激活等状态,响应系统级事件(如窗口关闭、应用激活)。
实例:
javascript
// main.js(主进程)
const { app } = require('electron');
// 应用初始化完成后触发(必须在此时创建窗口)
app.whenReady().then(() => {
console.log('应用已就绪');
createWindow(); // 自定义创建窗口的函数
});
// 所有窗口关闭时触发(Windows/Linux下退出应用)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') { // 排除macOS(macOS窗口关闭后应用仍驻留)
app.quit();
}
});
// macOS下点击 Dock 图标时激活应用
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow(); // 重新创建窗口
}
});
2. 创建与管理窗口(渲染进程载体)
通过BrowserWindow
创建窗口,每个窗口对应一个独立的渲染进程,主进程控制窗口的大小、位置、显示/隐藏等。
实例:
javascript
// main.js(主进程)
const { BrowserWindow } = require('electron');
const path = require('path');
function createWindow() {
// 创建主窗口(渲染进程的载体)
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js'), // 预加载脚本(进程通信桥梁)
contextIsolation: true // 强制开启上下文隔离(安全要求)
}
});
// 加载渲染进程页面(HTML文件)
mainWindow.loadFile('index.html');
// 控制窗口行为(如最大化、最小化)
mainWindow.maximize(); // 窗口最大化
}
3. 访问系统资源(渲染进程无权直接访问)
主进程运行在Node.js环境,可直接访问文件系统、环境变量、系统命令等敏感资源,渲染进程需通过主进程间接访问。
实例:主进程读取环境变量并处理文件:
javascript
// main.js(主进程)
const fs = require('fs');
const path = require('path');
// 读取系统环境变量(渲染进程无法直接访问process.env)
const apiBaseUrl = process.env.API_BASE_URL || 'https://default-api.com';
// 写入文件(渲染进程无权直接调用fs模块)
function writeToFile(content) {
fs.writeFileSync(path.join(__dirname, 'data.txt'), content);
}
4. 作为进程间通信(IPC)的中介
主进程通过ipcMain
监听渲染进程的请求,处理后返回结果;也可主动通过webContents.send
向渲染进程发送消息。
实例:主进程处理渲染进程的"获取环境变量"请求:
javascript
// main.js(主进程)
const { ipcMain } = require('electron');
// 监听渲染进程的"get-env-vars"请求
ipcMain.handle('get-env-vars', () => {
// 筛选需要暴露给渲染进程的环境变量(避免敏感信息泄露)
return {
apiUrl: process.env.API_URL,
appMode: process.env.APP_MODE || 'development'
};
});
5. 管理菜单、托盘、对话框等系统级UI
主进程负责创建应用菜单、系统托盘图标、文件选择对话框等,这些是系统级交互,无法在渲染进程中直接实现。
实例:创建应用菜单:
javascript
// main.js(主进程)
const { Menu } = require('electron');
const menuTemplate = [
{
label: '文件',
submenu: [
{ label: '打开', click: () => console.log('打开文件') },
{ label: '保存', click: () => console.log('保存文件') }
]
}
];
const menu = Menu.buildFromTemplate(menuTemplate);
Menu.setApplicationMenu(menu); // 设置应用菜单
二、渲染进程如何从环境变量获取API参数配置?
渲染进程运行在Chromium环境中,默认无法直接访问process.env
(出于安全隔离,contextIsolation: true
时完全隔离Node API)。因此,需通过以下流程获取环境变量:
- 主进程读取环境变量 (主进程有权访问
process.env
); - 通过IPC通信将环境变量传递给渲染进程(主进程作为中介);
- 渲染进程调用预加载脚本暴露的接口获取变量。
详细步骤与实例:
1. 主进程准备环境变量并监听IPC请求
javascript
// main.js(主进程)
const { ipcMain } = require('electron');
// 1. 主进程读取环境变量(可从系统环境变量或配置文件获取)
const envConfig = {
apiBaseUrl: process.env.API_BASE_URL || 'https://api.example.com',
timeout: process.env.API_TIMEOUT || 5000,
// 敏感信息(如API密钥)不应暴露给渲染进程,主进程自行处理
// secretKey: process.env.SECRET_KEY // 仅主进程内部使用
};
// 2. 监听渲染进程的"get-env-config"请求,返回非敏感配置
ipcMain.handle('get-env-config', () => {
return envConfig; // 只返回渲染进程需要的非敏感配置
});
2. 预加载脚本(preload.js)暴露IPC接口
预加载脚本是唯一能在渲染进程中安全暴露主进程API的地方(运行在独立上下文,兼具Node和浏览器环境权限)。
javascript
// preload.js
const { contextBridge, ipcRenderer } = require('electron');
// 向渲染进程的全局对象(window)暴露安全接口
contextBridge.exposeInMainWorld('electronEnv', {
// 封装获取环境配置的方法(调用主进程的IPC接口)
getConfig: () => ipcRenderer.invoke('get-env-config')
});
3. 渲染进程调用接口获取环境变量
渲染进程通过预加载脚本暴露的window.electronEnv
获取配置。
html
<!-- index.html(渲染进程页面) -->
<!DOCTYPE html>
<html>
<body>
<div id="config"></div>
<script src="renderer.js"></script>
</body>
</html>
javascript
// renderer.js(渲染进程脚本)
// 调用预加载脚本暴露的接口获取环境配置
window.electronEnv.getConfig().then(config => {
console.log('从主进程获取的环境配置:', config);
// 输出:{ apiBaseUrl: "https://api.example.com", timeout: 5000 }
// 在页面中显示配置
document.getElementById('config').textContent =
`API地址:${config.apiBaseUrl},超时时间:${config.timeout}ms`;
});
4. 如何设置环境变量?
可通过启动命令传入环境变量(推荐使用cross-env
跨平台设置):
bash
# 安装cross-env(跨平台设置环境变量的工具)
npm install cross-env --save-dev
在package.json
中配置启动脚本:
json
{
"scripts": {
"start": "cross-env API_BASE_URL=https://dev-api.example.com electron .",
"start:prod": "cross-env API_BASE_URL=https://prod-api.example.com electron ."
}
}
运行时,主进程的process.env.API_BASE_URL
会被设置为对应的值。
三、关键注意事项
-
敏感信息不得暴露给渲染进程 :
如API密钥、数据库密码等,必须由主进程保管并直接处理相关逻辑(如发起带密钥的请求),避免通过IPC传递给渲染进程。
-
环境变量需过滤后传递 :
主进程应仅将渲染进程必需的非敏感配置(如API地址、超时时间)传递给渲染进程,避免暴露系统级环境变量(如
PATH
、HOME
)。 -
禁用
nodeIntegration: true
:开启
nodeIntegration
会让渲染进程直接访问Node API(包括process.env
),存在极大安全风险(如XSS攻击可能读取系统文件),必须保持默认的nodeIntegration: false
。 -
依赖预加载脚本通信 :
渲染进程与主进程的所有通信必须通过预加载脚本的
contextBridge
暴露,禁止直接在渲染进程中引入electron
模块。
总结
- 主进程是系统资源管理者和进程中介,负责窗口管理、环境变量读取、安全逻辑处理等核心功能;
- 渲染进程 需通过IPC向主进程请求环境变量,不可直接访问
process.env
; - 通信必须通过预加载脚本的
contextBridge
实现,确保安全隔离。
这种设计既保证了应用的安全性,又明确了进程职责划分,是Electron开发的最佳实践。