无法在渲染器进程中使用 Node.js API

vik*_*rma 3 javascript node.js electron

无法在电子中使用任何电子或节点相关的操作。获取错误过程未定义。我检查了他们指导添加节点支持的各个地方,但这已经完成了,所以我的主要应用程序代码是

const electron = require("electron");
const { app, BrowserWindow } = electron;

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

  win.loadFile("index.html");
}

app.whenReady().then(createWindow);

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

app.on("activate", () => {
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow();
  }
});
Run Code Online (Sandbox Code Playgroud)

和 Index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello World!</title>
  </head>
  <body style="background: white">
    <h1>Hello World!</h1>
    <p>
      We are using node
      <script>
        document.write(process.versions.node);
      </script>
      , Chrome
      <script>
        document.write(process.versions.chrome);
      </script>
      , and Electron
      <script>
        document.write(process.versions.electron);
      </script>
      .
    </p>
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

aab*_*leh 9

更新:下面的答案是一种解决方法。你不应该禁用contextIsolation,也不应该启用nodeIntegration。相反,您应该使用预加载脚本contextBridge API

Electron 12 中contextIsolation现在默认是true

如果您将其设置为false,您将可以在渲染器进程中访问 Node.js API

function createWindow() {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: { 
     contextIsolation: false,
     nodeIntegration: true
    },
  });

  win.loadFile("index.html");
}
Run Code Online (Sandbox Code Playgroud)

?? 需要注意的是,不推荐这样做!

Electron 维护者更改默认值是有充分理由的。看到这个讨论

如果没有 contextIsolation,渲染器进程中运行的任何代码都可以很容易地进入 Electron 内部或您的预加载脚本,并执行您不希望任意网站执行的特权操作。

  • 好的,但我没有在渲染器中运行“任意网站”。我正在运行我的应用程序!我不明白这怎么是一个“安全问题”? (4认同)
  • @vikrantverma 只是在此处添加,出于安全原因,您可能确实希望启用“contextIsolation”。请参阅[此处]的答案(/sf/answers/4655654671/) (3认同)

cus*_*der 8

没有理由提升渲染器的权限。该页面上的任何第三方脚本都将以相同的权限运行,这绝对不是您想要的。

相反,您应该使用具有该权限的预加载脚本(即默认情况下可以使用 Node.js API)但保留contextIsolation=true(无论如何这是默认值)。如果您需要在预加载脚本和渲染器脚本之间共享数据,请使用contextBridge.

在我的示例中,我在一个相当愚蠢的命名空间 ( ) 下将预加载脚本中的数据暴露给渲染器脚本,window.BURRITO以明显表明您负责:

main.js

const {app, BrowserWindow} = require('electron'); //<- v13.1.7
const path = require('path');

app.whenReady().then(() => {
  const preload = path.join(__dirname, 'preload.js');
  const mainWindow = new BrowserWindow({ webPreferences: { preload }});
  mainWindow.loadFile('index.html');
});
Run Code Online (Sandbox Code Playgroud)

预加载.js

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

contextBridge.exposeInMainWorld('BURRITO', {
  getNodeVer: () => process.versions.node,
  getChromeVer: () => process.versions.chrome,
  getElectronVer: () => process.versions.electron
});
Run Code Online (Sandbox Code Playgroud)

渲染器.js

const onClick = (sel, fn) => document.querySelector(sel).addEventListener('click', fn);
onClick('#btn1', () => alert(BURRITO.getNodeVer()));
onClick('#btn2', () => alert(BURRITO.getChromeVer()));
onClick('#btn3', () => alert(BURRITO.getElectronVer()));
Run Code Online (Sandbox Code Playgroud)

索引.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
  </head>
  <body>
    <button id="btn1">Node?</button>
    <button id="btn2">Chrome?</button>
    <button id="btn3">Electron?</button>
    <script src="./renderer.js"></script>
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述