Electron React项目引入whatsapp-web.js报fluent-ffmpeg编译错误怎么解决
问题原因
你遇到的报错本质是
whatsapp-web.js是纯Node.js环境专用的依赖包,不能直接在Electron的渲染进程(React代码属于渲染进程)中导入。
React的前端构建链(webpack/vite等)会解析所有导入的依赖,而fluent-ffmpeg作为whatsapp-web.js的依赖,包含大量Node专属的路径/API,前端打包工具无法识别处理,因此抛出找不到模块的错误。
可行解决方案
1. 调整架构:所有whatsapp逻辑放Electron主进程运行
Electron的主进程可以直接访问所有Node.js API,完全兼容whatsapp-web.js,渲染进程仅通过IPC通道和主进程通信即可。
第一步:新增preload.js(IPC通信桥接文件)
在和main.js同级目录新建preload.js,内容如下:
const { contextBridge, ipcRenderer } = require('electron'); // 向渲染进程暴露安全的通信接口 contextBridge.exposeInMainWorld('electronAPI', { initWhatsapp: () => ipcRenderer.invoke('init-whatsapp'), onQrReceived: (callback) => ipcRenderer.on('whatsapp-qr', (_, qrCode) => callback(qrCode)), onClientReady: (callback) => ipcRenderer.on('whatsapp-ready', callback) })
第二步:修改main.js配置与逻辑
更新BrowserWindow的webPreferences配置,同时添加whatsapp相关初始化逻辑:
// Modules to control application life and create native browser window const { app, BrowserWindow, ipcMain } = require("electron"); const path = require("path"); // 主进程导入whatsapp相关依赖 const qrcode = require('qrcode-terminal'); const { Client } = require('whatsapp-web.js'); let mainWindow; function createWindow() { // Create the browser window. mainWindow = new BrowserWindow({ width: 800, height: 600, webPreferences: { webSecurity: false, contextIsolation: true, // 必须开启,保证安全 nodeIntegration: false, // 禁止渲染进程直接访问Node API preload: path.join(__dirname, 'preload.js') // 关联preload文件 }, }); // and load the index.html of the app. mainWindow.loadURL("your ip address:3000"); // Open the DevTools. // mainWindow.webContents.openDevTools() } // 监听渲染进程的初始化请求 ipcMain.handle('init-whatsapp', async () => { const client = new Client(); // 收到二维码时发送给渲染进程 client.on('qr', (qr) => { qrcode.generate(qr, {small: true}); mainWindow.webContents.send('whatsapp-qr', qr); }); // 客户端就绪后通知渲染进程 client.on('ready', () => { mainWindow.webContents.send('whatsapp-ready'); }); client.initialize(); return true; }) app.whenReady().then(() => { createWindow(); app.on("activate", function () { // On macOS it's common to re-create a window in the app when the // dock icon is clicked and there are no other windows open. if (BrowserWindow.getAllWindows().length === 0) createWindow(); }); }); // Quit when all windows are closed, except on macOS. There, it's common // for applications and their menu bar to stay active until the user quits // explicitly with Cmd + Q. app.on("window-all-closed", function () { if (process.platform !== "darwin") app.quit(); }); // In this file you can include the rest of your app's specific main process // code. You can also put them in separate files and require them here.
第三步:修改React组件代码
删除所有直接导入whatsapp-web.js、qrcode-terminal的逻辑,改用暴露的IPC接口通信:
import React, { useEffect } from "react"; import styled from "styled-components"; function Error() { useEffect(() => { // 初始化whatsapp客户端 window.electronAPI.initWhatsapp(); // 监听二维码事件,可自行转成图片展示 window.electronAPI.onQrReceived((qrCode) => { console.log('收到登录二维码:', qrCode); }); // 监听就绪事件 window.electronAPI.onClientReady(() => { console.log('whatsapp客户端已就绪'); }); }, []) return ( <Container> <ErrorImage src="https://cdn4.iconfinder.com/data/icons/smiley-vol-3-2/48/134-512.png"></ErrorImage> <ErrorMessage>Oops, you are not connected to any number.</ErrorMessage> </Container> ); } export default Error; const Container = styled.div` display: flex; height: 100vh; width: 100%; padding-top: 20vh; position: center; /* align-items: center; */ justify-content: center; `; const ErrorImage = styled.img` background-color: transparent; background-repeat: no-repeat; background-size: cover; object-fit: contain; width: 25%; height: 25%; /* border: 2px solid black; */ `; const ErrorMessage = styled.div` margin: 10px; width: 50%; height: 25%; /* top: 20px; */ font-size: 30px; align-items: center; font-family: "Lucida Console", "Courier New", monospace; /* font-weight: bold; */ `;
2. 残留打包报错处理
如果修改后打包时仍有fluent-ffmpeg相关报错,根据你使用的构建工具添加外部依赖配置即可:
- 若用create-react-app,通过craco修改webpack配置,新增如下规则:
// craco.config.js module.exports = { webpack: { configure: (config) => { config.externals = { 'fluent-ffmpeg': 'commonjs fluent-ffmpeg', 'whatsapp-web.js': 'commonjs whatsapp-web.js' } return config; } } }
- 若用electron-builder打包主进程,在package.json的build配置中添加:
"build": { "externals": ["fluent-ffmpeg", "whatsapp-web.js"] }
内容的提问来源于stack exchange,提问作者Sunil Shah
相关产品推荐
相关产品推荐

