如何修复CRA+Electron引入ipcRenderer时fs.existsSync不是函数的错误
问题原因
你遇到的报错是因为CRA(Create React App)默认会把所有依赖打包到前端bundle中,你在渲染层代码里require("electron")时,webpack直接引入了node_modules/electron下的源码,该源码依赖Node.js的fs模块,但前端打包后的代码运行在浏览器沙箱环境中,没有fs相关API,所以触发了报错。即使你开启了nodeIntegration,也会因为webpack提前打包了electron模块导致无法调用Electron运行时暴露的原生API。
解决方案
推荐使用更安全的**预加载脚本(Preload)**方案,不需要开启不安全的Node集成,符合Electron官方最佳实践,操作步骤如下:
步骤1:修改主进程窗口配置
修改main.js中BrowserWindow的webPreferences配置,指定预加载脚本路径,保留默认安全配置:
const path = require("path"); // ...其余原有代码 function createWindow() { const win = new BrowserWindow({ width: 800, height: 600, webPreferences: { // 新增预加载脚本配置,填你实际存放preload.js的路径 preload: path.join(__dirname, "preload.js"), // 保留默认安全配置,无需开启nodeIntegration contextIsolation: true, nodeIntegration: false } }); // ...其余原有窗口加载逻辑 }
步骤2:创建预加载脚本
在main.js同级目录新建preload.js,通过contextBridge将需要用到的IPC能力暴露给渲染进程:
const { contextBridge, ipcRenderer } = require("electron"); contextBridge.exposeInMainWorld("electronAPI", { // 触发Playwright自动化任务 runAutomation: (taskParams) => ipcRenderer.invoke("run-automation", taskParams), // 接收自动化任务进度回调,可根据需要扩展 onTaskProgress: (callback) => ipcRenderer.on("task-progress", (_, data) => callback(data)) });
步骤3:主进程封装自动化逻辑并监听IPC事件
修改main.js,将你原有写死的Playwright逻辑封装成可调用的函数,同时监听渲染进程的IPC调用:
const { ipcMain } = require("electron"); const { firefox } = require('playwright'); // 封装自动化任务逻辑 async function runAutomation(taskParams) { // taskParams可以接收渲染层传过来的账号、密码、操作参数等 const { email, password } = taskParams; try { const browser = await firefox.launch({ headless: false, slowMo: 50 }); const context = await browser.newContext(); const page = await context.newPage(); await page.goto('你的目标网站地址'); await page.waitForTimeout(2000); await page.waitForLoadState('load'); const input1 = await page.$('[id ="exampleInputEmail1"]'); await input1.type(email) await page.waitForTimeout(2000); const input2 = await page.$('[id ="exampleInputPassword1"]'); await input2.type(password) await page.waitForTimeout(2000); await page.click('"Sign In and Continue"') await page.waitForTimeout(2000); // 其余自动化逻辑 return { success: true }; } catch (e) { return { success: false, error: e.message }; } } // 监听渲染进程的自动化调用请求 ipcMain.handle("run-automation", async (_, taskParams) => { return await runAutomation(taskParams); });
步骤4:渲染层调用IPC方法
现在渲染层不需要再引入electron,直接通过全局暴露的electronAPI调用即可:
// 渲染层触发自动化的代码示例 async function startAutoTask() { const result = await window.electronAPI.runAutomation({ email: "你的账号", password: "你的密码" }); console.log("任务执行结果:", result); }
快速适配方案(不推荐,仅用于快速验证)
如果你暂时不需要考虑安全问题,想要快速适配现有代码,可以按以下操作:
- 安装
react-app-rewired和customize-cra修改CRA默认webpack配置:
npm install react-app-rewired customize-cra --save-dev
- 项目根目录新建
config-overrides.js,配置electron为外部依赖不打包:
const { override, addWebpackExternals } = require('customize-cra'); module.exports = override( addWebpackExternals({ electron: 'commonjs electron' }) );
- 修改
package.json的scripts字段,将react-scripts替换为react-app-rewired:
"scripts": { "start": "react-app-rewired start", "build": "react-app-rewired build", "test": "react-app-rewired test", "eject": "react-scripts eject" }
- 修改
main.js的webPreferences配置:
webPreferences: { nodeIntegration: true, contextIsolation: false }
完成后你在渲染层const { ipcRenderer } = require("electron")就不会报错了。
内容的提问来源于stack exchange,提问作者MartinDuo
相关产品推荐
相关产品推荐

