在Electron中,如何在React代码中启用NodeJS?

rn0zuynd  于 2023-01-10  发布在  Electron
关注(0)|答案(2)|浏览(270)

在Electron中,如何在React代码中启用NodeJS?
我需要采取哪些步骤?我正在尝试访问通常在节点中使用以下命令访问的文件系统组件:

const fs = require('fs');

在我的React代码中,这没有编译,所以我尝试将其更改为导入,但也不起作用。

import fs from 'fs';
// Gives error
Module not found: Error: Can't resolve 'fs' ...

在寻找解决方案时,我发现了一些问题,但(目前)还没有答案:

我看到一个与此匹配的SO问题/答案,但现在找不到!
我已经启用NodeJS在我的电子主应用程序使用:

mainWindow = new BrowserWindow({
    width: winState.width,
    height: winState.height,
    x: winState.x,
    y: winState.y,
    webPreferences: {
      // --- !! ANT !! ---
      // Disable 'contextIsolation' to allow 'nodeIntegration'
      // 'contextIsolation' defaults to "true" as from Electron v12
      contextIsolation: false,
      nodeIntegration: true, /* Allow NodeJS code to be called in Web Pages */
      enableRemoteModule: true
    }
  })
q8l4jmvw

q8l4jmvw1#

要访问带有React的电子应用程序内的文件系统,您需要代码库的三个不同部分:

  • 主进程,它运行在Node中,可以访问fs和Node拥有的其他所有东西。这可能最终调用new BrowserWindow,它打开一个窗口和runs the preload script
  • 预加载脚本是用来管理主进程和浏览器之间的通信的,虽然它可以做得更多,但它真的不应该做;它最好只作为一个桥梁。你的预加载脚本可以像这样简单
contextBridge.exposeInMainWorld('electronAPI', {
  sendMessageToMainProcess: (channel, payload) => ipcRenderer.invoke(channel, payload),
})
  • 运行React代码的页面脚本(以及在窗口中运行的任何其他代码)。它在类似于浏览器的上下文中运行,并且不能访问任何Node函数。为了从页面动态读取文件系统,页面需要向主进程发送消息(通过预加载脚本所暴露的API),然后主进程将需要监听消息,运行所需的任何fs操作,然后使用结果回复消息。上面的electronAPI示例可以从React with window.electronAPI.sendMessageToMainProcess(channel, payload)调用。主进程可以侦听消息(通过预加载脚本附加)并使用以下命令回复消息,例如
ipcMain.handle('someChannelName', (event, payload) => {
  // do verification here if desired...
  return fs.promises.readFile('somepath', 'utf-8')
    // .catch(handleErrors);
});

通过从处理函数返回Promise,Promise解析的值将被发送回调用方。
上面的设置非常简单,不需要unsafe contextIsolation: falsenodeintegration: true
自Electron 12以来,上下文隔离已默认启用,并且它是所有应用程序的推荐安全设置。
如果页面脚本中的 any 代码不是您个人的(例如,如果您使用外部库或很少的库-如React),那么您不应该允许页面脚本直接访问Node或您的文件系统。

thigvfpy

thigvfpy2#

在电子应用程序中,使用NodeJS require函数的方法是使用window.require,如下所示:

const fs = window.require('fs');

只有在创建BrowserWindow时首先启用nodeIntegration: true,此选项才有效。

mainWindow = new BrowserWindow({
      nodeIntegration: true, 
});

正如@CertainPerformance所说,这真的是一个黑客。我在第一次开始使用它,因为它比学习如何通过 * 电子IPC* 机制(ipcRenderer.invoke)完成等效功能更容易。

相关问题