TypeError: fs.existsSync is not a function | import { ipcRenderer } from 'electron'

发布时间 2023-08-08 16:31:06作者: 孙凯亮

在electron的渲染进程中导包会发生TypeError: fs.existsSync is not a function node_modules/electron/index.js:6

var pathFile = path.join(__dirname, 'path.txt')

if (fs.existsSync(pathFile)) {
  module.exports = path.join(__dirname, fs.readFileSync(pathFile, 'utf-8'))
} else {
  throw new Error('Electron failed to install correctly, please delete node_modules/electron and try installing again')
}

产生问题的原因:
1、首先在渲染进程属于浏览器端,没有集成Node的环境,所以类似 fs 这样的Node的基础包是不可以使用。

2、因为没有Node环境,所以require关键词是不可以使用的。

弄清楚这个就一起解决问题吧:

方案一:

渲染进程

const { ipcRenderer } = window.require('electron');
主进程

const win = new BrowserWindow({
    webPreferences: {
      nodeIntegration: true
    }
  })

使用这种方式能够是electron为前端工程提供Node的环境,让程序能够正常运行。

但是,单独启动前端工程会出现 window.require is not a function .

方案二:

来源于StackOverflow

1、创建 a preload.js 文件:

window.ipcRenderer = require('electron').ipcRenderer;

2、在main.js文件中的 webPreferen中设置预加载preload:

mainWindow = new BrowserWindow({
    width: 800, 
    height: 600,
    webPreferences: {
      nodeIntegration: false,
      preload: __dirname + '/preload.js'
    }
  });

3、渲染进程

componentDidMount() {
		  if (isElectron()) {
			console.log(window.ipcRenderer);
			window.ipcRenderer.on('pong', (event, arg) => {
				this.setState({ipc: true})
			})
			window.ipcRenderer.send('ping')
		}
	}

is-electron for the isElectron() function

方案三:

来源以 github

如果你使用TypeScript可以这样做:

import {IpcRenderer} from 'electron';

declare global {
  interface Window {
    require: (module: 'electron') => {
      ipcRenderer: IpcRenderer
    };
  }
}

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

方案四:

读了N个electron项目后,写成的一种解决方案:

直接上代码

externals(context, request, callback) {
    const isDev = process.env.NODE_ENV === 'development';
    let isExternal = false;
    const load = [
      'electron',
      'fs',
      'path',
      'os',
      'url',
      'child_process'
    ];
    if (load.includes(request)) {
      isExternal = `require("${request}")`;
    }
    const appDeps = Object.keys(require('./app/package').dependencies);
    if (appDeps.includes(request)) {
      const orininalPath = slash(join(__dirname, './app/node_modules', request));
      const requireAbsolute = `require('${orininalPath}')`;
      isExternal = isDev ? requireAbsolute : `require('${request}')`;
    }
    callback(null, isExternal);
  },

发现了吗,在前端工程配置的时候,默认设置externals参数,在使用require的时候会查看默认加载的模块中有没有,按需加载模块,如果初始加载的模块中没有该模块,会向上级目录./app/package查找模块。