You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Electron渲染进程结合Webpack使用Node.js插件报错的解决方法

问题描述

我有如下渲染进程代码:

import SerialPort from "serialport";
new SerialPort("/dev/tty-usbserial1", { baudRate: 57600 });

该代码由Webpack构建,相关配置(简化后)如下:

const config = {
  entry: { renderer: ["./src/renderer"] },
  output: {
    path: `${__dirname}/dist`,
    filename: "[name].js",
  },
  target: "electron-renderer",
  node: false, // 禁用__dirname模拟等功能
};

代码由开发服务器提供服务,搭配index.html,并由主进程作为网页加载(这是开发时热模块替换所需)。

主进程同样由Webpack构建并输出到dist目录,Webpack插件还生成了如下dist/package.json:

{
  "name": "my-app",
  "main": "main.js"
}

当我运行electron dist时,渲染进程崩溃并抛出如下错误:

Uncaught TypeError: Path must be a string. Received undefined
at assertPath (path.js:28)
at dirname (path.js:1364)
at Function.getRoot (bindings.js?dfc1:151)
at bindings (bindings.js?dfc1:60)
at eval (linux.js?d488:2)
at Object../node_modules/serialport/lib/bindings/linux.js (renderer.js:12686)
at __webpack_require__ (renderer.js:712)
at fn (renderer.js:95)
at eval (auto-detect.js?3cc7:16)
at Object../node_modules/serialport/lib/bindings/auto-detect.js (renderer.js:12638)

请问该如何解决这个问题?


解决方案

这个问题本质是serialport这类原生Node.js模块在Electron渲染进程被Webpack打包时的路径解析冲突——你设置node: false完全禁用了Node.js全局变量模拟,导致serialport依赖的bindings模块无法正确获取文件路径。下面给你几个实用的解决思路:

1. 让Webpack跳过serialport的打包

原生模块包含二进制文件,本来就不适合被Webpack打包处理。你可以在Webpack配置里添加externals,告诉Webpack直接在运行时通过require加载serialport:

const config = {
  // ... 其他原有配置
  externals: {
    serialport: "require('serialport')"
  }
};

这样Webpack会把渲染进程里的import SerialPort from 'serialport'替换为运行时的require('serialport'),让Electron直接从node_modules加载原生模块,避免路径解析错误。

2. 按需启用Node.js全局变量模拟

你不需要完全禁用所有Node.js全局变量,只需要启用bindings模块需要的__dirname和__filename即可:

const config = {
  // ... 其他原有配置
  node: {
    __dirname: true,
    __filename: true
  }
};

这种方式既能保留你禁用其他Node.js全局变量的需求,又能让serialport的依赖模块正确解析路径。

3. 主进程处理串口逻辑,通过IPC和渲染进程通信

这是更符合Electron安全规范的做法——渲染进程如果开启Node.js集成存在安全风险,而原生模块操作放在主进程更稳妥。你可以通过Electron的IPC机制实现渲染进程和主进程的通信:

主进程代码示例

const { ipcMain } = require('electron');
const SerialPort = require('serialport');

// 初始化串口
const port = new SerialPort("/dev/tty-usbserial1", { baudRate: 57600 });

// 接收渲染进程的发送数据请求
ipcMain.handle('serial-send-data', async (event, data) => {
  port.write(data);
});

// 向渲染进程传递串口接收的数据
ipcMain.on('serial-listen-data', (event) => {
  port.on('data', (data) => {
    event.reply('serial-received-data', data.toString());
  });
});

渲染进程代码示例

const { ipcRenderer } = require('electron');

// 发送数据到串口
ipcRenderer.invoke('serial-send-data', 'Hello Serial Port!');

// 监听串口返回的数据
ipcRenderer.on('serial-received-data', (event, data) => {
  console.log('Received from serial:', data);
});

额外注意事项

  • 如果你的serialport安装后无法正常运行,记得用electron-rebuild重新编译适配Electron版本的原生模块:
    npx electron-rebuild
    
  • 开发模式下使用热加载时,主进程的修改需要重启Electron才能生效,可以搭配electronmon这类工具实现主进程自动重启。

内容的提问来源于stack exchange,提问作者Alec Mev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:06:56