nodeIntegration
## 一、基本作用 在Electron中,`nodeIntegration: true`的作用主要是允许渲染进程(即BrowserWindow实例所代表的进程)访问Node.js的API和环境。以下是对其作用的具体解释: **启用Node.js集成**:当nodeIntegration设置为true时,渲染进程将能够使用Node.js的模块和API。 这意味着在渲染进程的JavaScript代码中,你可以通过`require`函数导入Node.js模块,并使用这些模块提供的功能。 --- ## 二、应用场景 **增强渲染进程的能力**:通过访问Node.js的API,渲染进程可以执行文件系统操作、网络通信等底层任务,从而增强应用的功能。 **实现前后端交互**:在Electron应用中,主进程通常负责处理底层逻辑和与操作系统的交互,而渲染进程负责呈现用户界面。 通过启用nodeIntegration,渲染进程可以直接与Node.js后端进行通信,实现前后端的无缝交互。 --- ## 三、注意事项 **安全性**:启用nodeIntegration可能会带来安全风险,因为渲染进程将能够执行任意Node.js代码。 因此,在开发Electron应用时,需要谨慎考虑是否需要启用此选项, 并采取必要的安全措施来保护应用免受恶意代码的攻击。 **Electron版本差异**:在Electron 5.0.0及更高版本中,nodeIntegration默认被禁用。 因此,如果你需要启用它,需要在BrowserWindow的webPreferences中明确设置`nodeIntegration: true`。 **contextIsolation**:在启用nodeIntegration时,建议同时启用contextIsolation(设置为true)。 这可以将渲染进程的JavaScript上下文与Node.js环境隔离,从而降低安全风险。 然而,需要注意的是,启用contextIsolation后,将无法使用remote模块直接在渲染进程中调用主进程的方法。 此时,需要通过其他方式(如IPC通信)来实现前后端的交互。 **综上所述**,`nodeIntegration: true`在Electron中的作用是允许渲染进程访问Node.js的API和环境,从而增强应用的功能。 然而,在启用此选项时,需要谨慎考虑安全性问题,并采取必要的措施来保护应用的安全。
process
## process.platform `process.platform` 属性返回一个字符串,标识编译 Node.js 二进制文件的操作系统平台。 ### 可能的值 Currently possible values are: 'aix' 'darwin' 'freebsd' 'linux' 'openbsd' 'sunos' 'win32' ### 示例代码 ```javascript const { platform } = require('node:process'); console.log(`This platform is ${platform}`); ``` ### 参考文档 https://nodejs.org/api/process.html#process_process_platform
## Electron 进程模型说明总结 Electron 继承了 Chromium 的多进程架构,主要由主进程、渲染进程和工具进程组成。以下是各进程的核心功能总结: ### 一、进程类型对比 | 进程类型 | 运行环境 | 核心功能 | 关键特性 | |---------|---------|---------|---------| | **主进程** | Node.js | 应用入口点、窗口管理、生命周期控制、原生API调用 | 每个应用只有一个;可创建和管理BrowserWindow;控制应用生命周期(app模块);提供原生桌面功能(菜单、对话框等) | | **渲染进程** | 浏览器环境 | 负责页面渲染和UI交互 | 每个窗口独立进程;遵循Web标准;不能直接访问Node.js API;可使用HTML/CSS/JavaScript构建界面 | | **预加载脚本** | 混合环境 | 在渲染进程加载前执行,桥接主进程和渲染进程 | 可访问Node.js API;与渲染进程共享window全局;使用contextBridge安全暴露API | | **工具进程** | Node.js | 处理不可信服务、CPU密集型任务、易崩溃组件 | 通过UtilityProcess API创建;支持与渲染进程通过MessagePort通信 | ### 二、进程间通信与交互 **主进程 ↔ 渲染进程** - 通过 `ipcRenderer` 和 `ipcMain` 模块进行进程间通信 - 预加载脚本通过 `contextBridge.exposeInMainWorld` 安全暴露API **预加载脚本示例** ```javascript // preload.js const { contextBridge } = require('electron') contextBridge.exposeInMainWorld('myAPI', { desktop: true }) // renderer.js console.log(window.myAPI) // => { desktop: true } ``` ### 三、TypeScript类型支持 | 路径别名 | 包含类型 | |---------|---------| | `electron/main` | 主进程模块类型定义 | | `electron/renderer` | 渲染进程模块类型定义 | | `electron/common` | 跨进程通用模块类型定义 | ### 四、设计优势 多进程架构的主要优势在于**隔离性**——单个渲染进程崩溃不会影响整个应用,这与现代浏览器的设计理念一致,既提升了稳定性也增强了安全性。
## process.env 简介 `process.env` 是 Node.js 中的一个全局对象,包含了当前进程的环境变量。在 Electron 应用中,我们可以通过它来读取和设置环境变量,实现配置管理和跨平台兼容。 --- ## 一、基本概念 ### 什么是环境变量? 环境变量是操作系统存储的键值对,用于配置系统和应用程序的行为。例如: - `PATH`:系统可执行文件搜索路径 - `NODE_ENV`:Node.js 运行环境(development/production) - `USER`:当前用户名 ### process.env 的作用 | 功能 | 说明 | |------|------| | **读取配置** | 从 `.env` 文件或系统环境变量中读取应用配置 | | **环境判断** | 区分开发/生产环境,执行不同逻辑 | | **路径管理** | 获取用户目录、系统目录等信息 | | **跨平台兼容** | 根据不同平台设置不同的配置 | --- ## 二、D:\wks\elec 项目中的使用 ### 1. .env 文件配置 在 `D:\wks\elec\.env` 中定义环境变量: ```env # Vite 开发服务器配置 VITE_PORT=5273 VITE_HOST=0.0.0.0 # Electron 配置 ELECTRON_DEV_URL=http://localhost:5273 # API 配置 VITE_API_BASE=http://127.0.0.1:8888/api/v1 # 应用配置 NODE_ENV=development ``` ### 2. main.js 中读取环境变量 ```javascript // 加载 .env 文件 require('dotenv').config(); // 读取环境变量(带默认值) const ELECTRON_DEV_URL = process.env.ELECTRON_DEV_URL || 'http://localhost:5173'; const NODE_ENV = process.env.NODE_ENV || 'development'; // Windows 平台特殊处理 if (process.platform === 'win32') { process.env.NODE_ENV = process.env.NODE_ENV || 'development'; } ``` ### 3. 常用 process.env 属性 | 属性 | 说明 | 示例值 | |------|------|--------| | `NODE_ENV` | 运行环境 | `'development'` / `'production'` | | `ELECTRON_DEV_URL` | 开发服务器地址 | `'http://localhost:5273'` | | `VITE_PORT` | Vite 端口 | `'5273'` | | `VITE_API_BASE` | API 基础路径 | `'http://127.0.0.1:8888/api/v1'` | --- ## 三、实际应用场景 ### 场景 1:环境判断 ```javascript const isDev = process.env.NODE_ENV === 'development' || process.env.NODE_ENV === undefined || !app.isPackaged; if (isDev) { // 开发环境:加载本地 Vite 服务器 mainWindow.loadURL(ELECTRON_DEV_URL); mainWindow.webContents.openDevTools(); } else { // 生产环境:加载打包后的文件 mainWindow.loadFile(path.join(__dirname, 'dist/index.html')); } ``` ### 场景 2:跨平台配置 ```javascript // Windows 平台特殊处理 if (process.platform === 'win32') { console.log('[Platform] Windows detected'); console.log('[Encoding] UTF-8 mode enabled'); // Windows GPU 配置 app.commandLine.appendSwitch('enable-gpu-rasterization'); app.commandLine.appendSwitch('disable-software-rasterizer'); } else if (process.platform === 'darwin') { // macOS 特定配置 app.commandLine.appendSwitch('enable-gpu-rasterization'); } ``` ### 场景 3:动态配置加载 ```javascript // 从环境变量读取 API 地址 const API_BASE = process.env.VITE_API_BASE || 'http://localhost:8888/api/v1'; // 在渲染进程中使用(通过 preload 脚本暴露) contextBridge.exposeInMainWorld('config', { apiBase: API_BASE, isDev: process.env.NODE_ENV === 'development' }); ``` --- ## 四、环境变量优先级 在 `D:\wks\elec` 项目中,环境变量的加载优先级: 1. **系统环境变量**(最高优先级) 2. **.env 文件**(通过 dotenv 加载) 3. **代码中的默认值**(作为后备) ```javascript // 优先级示例 const config = { apiUrl: process.env.API_URL || // 1. 系统环境变量 process.env.VITE_API_BASE || // 2. .env 文件 'http://localhost:8888/api/v1' // 3. 默认值 }; ``` --- ## 五、注意事项 | 注意事项 | 说明 | |---------|------| | **安全性** | 不要在 `.env` 文件中存储敏感信息(如密码、密钥) | | **版本控制** | 将 `.env` 添加到 `.gitignore`,提供 `.env.example` 作为模板 | | **类型转换** | `process.env` 的值都是字符串,需要手动转换为数字或布尔值 | | **打包部署** | 生产环境中需要在启动前设置环境变量 | **类型转换示例**: ```javascript // 错误:process.env 的值都是字符串 const port = process.env.VITE_PORT; // "5273" (字符串) const useSSL = process.env.USE_SSL; // "false" (字符串,不是布尔值) // 正确:手动转换 const port = parseInt(process.env.VITE_PORT) || 5273; const useSSL = process.env.USE_SSL === 'true'; ``` --- ## 六、参考文档 - [Node.js process.env 文档](https://nodejs.org/api/process.html#process_process_env) - [dotenv 包文档](https://www.npmjs.com/package/dotenv) - [Electron 环境变量最佳实践](https://www.electronjs.org/docs/latest/tutorial/faq#how-can-i-get-the-version-of-electron-and-versions-of-other-dependencies)
调试
## 调试相关资源 ### DevTools扩展 https://www.electronjs.org/zh/docs/latest/tutorial/devtools-extension ### 调试应用 https://www.electronjs.org/zh/docs/latest/tutorial/application-debugging
windows
## 渲染器进程 每个 Electron 应用都会为每个打开的 BrowserWindow ( 与每个网页嵌入 ) 生成一个单独的渲染器进程。 洽如其名,渲染器负责 **渲染** 网页内容。 ## Preload 脚本 预加载(preload)脚本包含了那些执行于渲染器进程中, 且先于网页内容开始加载的代码。 这些脚本虽运行于渲染器的环境中,却能访问 Node.js API 而拥有了更多的权限。 预加载脚本可以在 BrowserWindow 构造方法中的 webPreferences 选项里被附加到主进程。 ### 配置 preload 脚本 ```javascript const { BrowserWindow } = require('electron') // ... const win = new BrowserWindow({ webPreferences: { preload: 'path/to/preload.js' } }) // ... ``` ## Context Isolation(上下文隔离) 因为预加载脚本与浏览器共享同一个全局 Window 接口,并且可以访问 Node.js API, 所以它通过在全局 window 中暴露任意 API 来增强渲染器,以便你的网页内容使用。 Although preload scripts share a window global with the renderer they're attached to, you cannot directly attach any variables from the preload script to window because of the `contextIsolation` default. **语境隔离(Context Isolation)**意味着 预加载脚本与渲染器的主要运行环境 是隔离开来的, 以避免泄漏任何具特权的 API 到您的网页内容代码中。 Instead, use the `contextBridge` module to accomplish this securely: ### preload.js ```javascript contextBridge.exposeInMainWorld('versions', { node: () => process.versions.node, chrome: () => process.versions.chrome, electron: () => process.versions.electron, ping: () => ipcRenderer.invoke('ping'), globalVisitCount: true // 除函数之外,我们也可以暴露变量 }) ``` ### renderer.js ```javascript console.log(window.versions.globalVisitCount) // => { desktop: true } console.log(versions.globalVisitCount) // => { desktop: true } ``` **说明**:`contextBridge.exposeInMainWorld`可以通过全局变量`window`打通 预加载脚本与渲染进程的脚本之间的隔离。
参考