字节笔记本

2026年2月22日

Electron + Vue.js 中正确导入 ipcRenderer 的完整指南

本文整理自 Stack Overflow 上的一个热门问题,介绍如何在 Vue.js 项目中正确导入 Electron 的 ipcRenderer,解决 __dirname is not defined 错误。

问题背景

在使用 Vue CLI Plugin Electron Builder 开发 Electron 应用时,开发者经常遇到如何在 Vue 组件中正确使用 ipcRenderer 的问题。特别是在启用 contextIsolation 的安全配置下,直接导入 ipcRenderer 会导致错误。

错误现象

当在 Vue 文件中尝试导入 ipcRenderer 时:

javascript
import { ipcRenderer } from 'electron'

可能会遇到以下错误:

  • __dirname is not defined
  • fs.existsSync is not a function

解决方案

1. 配置 vue.config.js

首先需要在项目根目录的 vue.config.js 中配置 preload 文件路径:

javascript
// vue.config.js
module.exports = {
  pluginOptions: {
    electronBuilder: {
      preload: 'src/preload.js',
      // 或者配置多个 preload 文件
      // preload: { preload: 'src/preload.js', otherPreload: 'src/preload2.js' }
    }
  }
}

2. 配置 background.js

src/background.js 中配置 webPreferences 使用 preload 文件:

javascript
// src/background.js
const win = new BrowserWindow({
  width: 800,
  height: 600,
  webPreferences: {
    nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
    contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION,
    enableRemoteModule: true,
    preload: path.join(__dirname, 'preload.js'),
  },
})

注意:默认情况下 nodeIntegration 是禁用的,contextIsolation 是启用的。

3. 创建 preload.js

src 目录下创建 preload.js 文件(注意不是 dist_electron 目录):

javascript
// src/preload.js
import { contextBridge, ipcRenderer } from 'electron'

// 将 ipcRenderer 暴露给客户端
contextBridge.exposeInMainWorld('ipcRenderer', {
  send: (channel, data) => {
    // 白名单通道
    let validChannels = ['nameOfClientChannel']
    if (validChannels.includes(channel)) {
      ipcRenderer.send(channel, data)
    }
  },
  receive: (channel, func) => {
    let validChannels = ['nameOfElectronChannel']
    if (validChannels.includes(channel)) {
      // 故意剥离 event 对象,因为它包含 sender
      ipcRenderer.on(channel, (event, ...args) => func(...args))
    }
  }
})

4. 在 Vue 组件中使用

配置完成后,可以在 Vue 组件中通过 window.ipcRenderer 访问:

vue
// src/App.vue
<template>
  <div>
    <button @click="test">发送消息</button>
  </div>
</template>

<script>
export default {
  name: "App",
  methods: {
    test() {
      window.ipcRenderer.send('channel', data)
    }
  }
}
</script>

5. 在主进程中监听

background.js 中监听渲染进程发送的消息:

javascript
// background.js
ipcMain.on('channel', (event, args) => {
  // 处理消息
})

安全注意事项

使用 contextBridgecontextIsolation 是 Electron 推荐的安全实践:

  1. contextIsolation: 防止原型污染攻击
  2. contextBridge: 安全地将特定的 API 暴露给渲染进程
  3. 通道白名单: 限制可以使用的 IPC 通道,防止未授权访问

调试技巧

可以在 preload.js 中添加 alert 来验证 preload 脚本是否正常工作:

javascript
alert("Preload 脚本加载成功!") // 确认后删除此行

参考资源

分享: