网站搜索

javascript - 如何在 Electron 中加载多个 preload.js 文件


如何导出 preload1、preload2、preload3 并将它们引入到 index 中?

index.ts

const test1 = require("./preload1")
const test2 = require("./preload2")
const test3 = require("./preload3")
const { contextBridge } = require('electron');

contextBridge.exposeInMainWorld('testApi', { test1, test2, test3 })

preload1.ts

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

const test1 = async () => {
  return await ipcRenderer.invoke('on-test-event')
}

export default {test1}

preload2.ts

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

const test2 = async () => {
  return await ipcRenderer.invoke('on-test-event')
}

export default {test2}

preload3.ts

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

const test3 = async () => {
  return await ipcRenderer.invoke('on-test-event')
}

export default {test3}

index.vue

console.log(testApi);

控制台错误

VM4 sandbox_bundle:93 Unable to load preload script: \electron-vite-vue\dist-electron\preloads\index.js


VM4 sandbox_bundle:93 Error: module not found: ./preload1
    at preloadRequire (VM4 sandbox_bundle:93:1386)
    at <anonymous>:2:17
    at runPreloadScript (VM4 sandbox_bundle:93:2211)
    at Object.<anonymous> (VM4 sandbox_bundle:93:2478)
    at ./lib/sandboxed_renderer/init.ts (VM4 sandbox_bundle:93:2632)
    at __webpack_require__ (VM4 sandbox_bundle:1:170)
    at VM4 sandbox_bundle:1:1242
    at ___electron_webpack_init__ (VM4 sandbox_bundle:1:1320)
    at VM4 sandbox_bundle:160:455

如果我把所有的预加载都写在索引中,它运行得很好:

index.ts

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

const test1 = async () => {
  return await ipcRenderer.invoke('on-test-event')
}

const test2 = async () => {
  return await ipcRenderer.invoke('on-test-event')
}

const test3 = async () => {
  return await ipcRenderer.invoke('on-test-event')
}

contextBridge.exposeInMainWorld('testApi', {test1, test2, test3})

控制台

{test1: ƒ, test2: ƒ, test3: ƒ}
 test1: ƒ ()
 test2: ƒ ()
 test3: ƒ ()
 [[Prototype]]: Object

答案#1

默认情况下,Electron 的进程是沙箱化的,这意味着你不能在渲染进程中使用 require,并且你只能在预加载脚本中 require 某些特定模块(特别强调我写的内容):

为了允许渲染器进程与主进程通信,附加到沙箱渲染器的预加载脚本仍将拥有经过填充的 Node.js API 子集。暴露了一个类似于 Node 的 require 模块的 require 函数,但只能导入 Electron 和 Node 内置模块的子集:[...]

如果你使用打包工具,你应该能够使用 import 语句来引入这些文件,而不是 require:

因为 require 函数是一个功能有限的 polyfill,你将无法使用 CommonJS 模块将你的 preload 脚本拆分成多个文件。如果你需要拆分 preload 代码,请使用诸如 webpack 或 Parcel 之类的打包工具。

但是,如果你真的想要/需要使用 require,你只能通过在 BrowserWindow 的 webPreferences 中禁用 sandbox 来实现:

const mainWindow = new BrowserWindow({
  webPreferences: {
    nodeIntegration: false,
    contextIsolation: true,
    sandbox: false
  }
});

但不要忘记,沙箱是一项安全功能,不建议关闭。