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

Angular与Electron IPC通信报错:无法解析fs/path模块

Electron + Angular IPC通信报错:无法解析fs/path模块

报错内容

./node_modules/electron/index.js:1:11-24 - Error: Module not found: Error: Can't resolve 'fs' in '/home/user/Desktop/project/node_modules/electron'

./node_modules/electron/index.js:2:13-28 - Error: Module not found: Error: Can't resolve 'path' in '/home/user/Desktop/project/node_modules/electron'

主进程代码(main.js)

const {app, ipcMain} = require('electron');
const {BrowserWindow} = require('electron');
const url = require("url");
const path = require("path");

let window

function createWindow () {
    window = new BrowserWindow({
        width: 800,
        height: 600,
        autoHideMenuBar: true,
        webPreferences: {
            nodeIntegration: true
        }
    });

    window.setMinimumSize(800, 600);

    window.loadURL( 
        url.format({
            pathname: path.join(__dirname, `/dist/music-converter/index.html`),
            protocol: "file:",
            slashes: true
        })
    );
}

app.on('ready', createWindow);

app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') app.quit()
})

app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
})

ipcMain.on('message-from-renderer', (event, arg) => {
    console.log(arg);
    event.reply('message-from-main', 'Message received in main process'); 
});

Angular组件代码

import { Component, OnInit } from '@angular/core';
import { ipcRenderer } from 'electron'

@Component({
  selector: 'file-browser',
  templateUrl: './file-browser.component.html',
  styleUrls: ['./file-browser.component.scss']
})

export class FileBrowserComponent implements OnInit {
  
  constructor() { }

  ngOnInit() {
    ipcRenderer.send('message-from-renderer', 'test');
  }
}

环境信息

  • Electron: 30.0.1
  • Angular: 16.2.0

已尝试但无效的方案

  • 更换导入方式,使用window.require:
    if ((<any>window).require) {
       this.ipcRenderer = (<any>window).require('electron').ipcRenderer;
    }
    
    或
    ngOnInit() {
       if ((<any>window).require) {
          const electron = (<any>window).require('electron');
          electron.ipcRenderer.send('message-from-renderer', 'test');
      } else {
         console.error('Electron is not available');
      }
    }
    
  • 配置webpack.config.js(已安装path-browserify):
    const webpack = require('webpack');
    
    module.exports = {
        plugins: [
            new webpack.ProvidePlugin({
                fs: 'empty',
                path: 'empty'
            })
        ]
    };
    
    或
    const path = require('path');
    
    module.exports = {
      resolve: {
        fallback: {
          fs: false,
          path: require.resolve('path-browserify')
        }
      }
    };
    
  • 修改package.json添加配置:
    "requires": true,
    "browser": {
      "fs": false,
      "path": false,
      "os": false
    }
    
  • 使用预加载脚本(未正确暴露IPC):
    preload.js:
    const fs = require('fs');
    const path = require('path');
    
    修改main.js的BrowserWindow配置:
    window = new BrowserWindow({
            width: 800,
            height: 600,
            autoHideMenuBar: true,
            webPreferences: {
                preload: path.join(__dirname, 'preload.js'),
                nodeIntegration: true
            }
        });
    

正确解决方案

1. 禁用Angular构建时对Electron模块的解析

在Angular项目根目录创建extra-webpack.config.js,添加如下配置:

module.exports = {
  externals: {
    electron: 'commonjs electron'
  }
};

安装@angular-builders/custom-webpack以支持自定义Webpack配置:

npm install @angular-builders/custom-webpack --save-dev

修改angular.json中的构建配置,将builder替换为自定义Webpack:
找到projects -> [你的项目名] -> architect -> build,修改:

"builder": "@angular-builders/custom-webpack:browser",
"options": {
  "customWebpackConfig": {
    "path": "./extra-webpack.config.js"
  },
  // 保留原有其他配置
}

同样修改serve配置的builder为@angular-builders/custom-webpack:dev-server。

2. 使用预加载脚本安全暴露IPC(符合Electron安全规范)

Electron 12+推荐关闭nodeIntegration,通过预加载脚本暴露必要API,而非直接开启node集成。

步骤1:编写预加载脚本(preload.js)

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

// 通过contextBridge安全暴露IPC方法到渲染进程
contextBridge.exposeInMainWorld('electronAPI', {
  sendMessage: (channel, data) => {
    ipcRenderer.send(channel, data);
  },
  receiveMessage: (channel, callback) => {
    ipcRenderer.on(channel, (event, ...args) => callback(...args));
  }
});

步骤2:修改main.js的BrowserWindow配置

关闭nodeIntegration,启用上下文隔离:

window = new BrowserWindow({
  width: 800,
  height: 600,
  autoHideMenuBar: true,
  webPreferences: {
    preload: path.join(__dirname, 'preload.js'),
    nodeIntegration: false, // 关闭node集成,符合安全规范
    contextIsolation: true // 启用上下文隔离,默认开启
  }
});

步骤3:修改Angular组件代码

通过全局window.electronAPI调用IPC方法,无需直接导入electron模块:

import { Component, OnInit } from '@angular/core';

// 声明全局类型,避免TypeScript报错
declare global {
  interface Window {
    electronAPI: {
      sendMessage: (channel: string, data: any) => void;
      receiveMessage: (channel: string, callback: (...args: any[]) => void) => void;
    };
  }
}

@Component({
  selector: 'file-browser',
  templateUrl: './file-browser.component.html',
  styleUrls: ['./file-browser.component.scss']
})
export class FileBrowserComponent implements OnInit {
  
  constructor() { }

  ngOnInit() {
    // 发送消息到主进程
    window.electronAPI.sendMessage('message-from-renderer', 'test');
    
    // 监听主进程回复
    window.electronAPI.receiveMessage('message-from-main', (message) => {
      console.log(message);
    });
  }
}

3. 重新构建并启动项目

ng build
electron .

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 02:45:23