出于安全考虑,渲染线程(来自 /src
的 UI 代码)无法访问 Node.js 内容。但是,你可以运行 Node.js 代码,并通过位于 /src-electron/electron-preload.js
的 Electron 预加载脚本将其桥接到渲染线程。使用 contextBridge
(来自 electron
包)来公开 UI 所需的内容。
¥For security reasons, the renderer thread (your UI code from /src
) does not have access to the Node.js stuff. However, you can run Node.js code and bridge it to the renderer thread through an Electron Preload script located at /src-electron/electron-preload.js
. Use contextBridge
(from the electron
package) to expose the stuff that you need for your UI.
由于预加载脚本是从 Node.js 运行的,因此在使用它以及暴露给渲染线程时请务必谨慎!
¥Since the preload script runs from Node.js, be careful what you do with it and what you expose to the renderer thread!
如何使用(How to use it)
¥How to use it
在 /src-electron/
文件夹中,有一个名为 electron-preload.js
的文件。填写你的预加载代码。
¥In /src-electron/
folder, there is a file named electron-preload.js
. Fill it with your preload code.
请确保你的 /src-electron/electron-main.js
包含以下内容(靠近 “webPreferences” 部分):
¥Make sure that your /src-electron/electron-main.js
has the following (near the “webPreferences” section):
// Add this at the top:
import path from 'path'
import { fileURLToPath } from 'url'
const currentDir = fileURLToPath(new URL('.', import.meta.url))
// ...
function createWindow () {
// ...
mainWindow = new BrowserWindow({
// ...
webPreferences: {
// HERE IS THE MAGIC:
preload: path.resolve(
currentDir,
path.join(process.env.QUASAR_ELECTRON_PRELOAD_FOLDER, 'electron-preload' + process.env.QUASAR_ELECTRON_PRELOAD_EXTENSION)
)
}
})
/src-electron/electron-preload.js
内容示例:
¥Example of /src-electron/electron-preload.js
content:
// example which injects window.myAPI.doAThing() into the renderer
// thread (/src/*)
const { contextBridge } = require('electron')
contextBridge.exposeInMainWorld('myAPI', {
doAThing: () => {}
})
警告
请注意,此文件在 Node.js 上下文中运行。
¥Be aware that this file runs in a Node.js context.
如果你从 node_modules 导入任何内容,请确保该包在 /package.json > “dependencies” 中指定,而不是在 “devDependencies” 中指定。
¥If you import anything from node_modules, then make sure that the package is specified in /package.json > “dependencies” and NOT in “devDependencies”.
安全注意事项(Security considerations)
¥Security considerations
仅仅使用 contextBridge
并不意味着你所做的一切都是安全的。例如,以下代码是不安全的:
¥Just by using contextBridge
does not automatically mean that everything you do is safe. For instance the code below is unsafe:
// BAD code; DON'T!!
contextBridge.exposeInMainWorld('myAPI', {
send: ipcRenderer.send
})
它直接暴露了强大的 API,无需任何参数过滤。这将允许任何网站发送你不希望发生的任意 IPC 消息。公开基于 IPC 的 API 的正确方法是为每个 IPC 消息提供一个方法。
¥It directly exposes a powerful API without any kind of argument filtering. This would allow any website to send arbitrary IPC messages which you do not want to be possible. The correct way to expose IPC-based APIs would instead be to provide one method per IPC message.
// Good code
contextBridge.exposeInMainWorld('myAPI', {
loadPreferences: () => ipcRenderer.invoke('myAPI:load-prefs')
})
现在,loadPreferences
在你的 JavaScript 代码中全局可用(即:window.myAPI.loadPreferences
)。
¥Now, loadPreferences
is available globally in your javascript code (ie: window.myAPI.loadPreferences
).
警告
请确保选择的名称与现有的 Window
键不冲突。
¥Make sure to pick names which do not colide with existing Window
keys.
在主线程中使用上述代码,将 invoke
连接到 load-prefs
,代码如下:
¥Using the above code with an invoke
to load-prefs
in the main thread would have code like this:
ipcMain.handle('myAPI:load-prefs', () => {
return {
// object that contains preferences
}
})
自定义预加载脚本路径(Custom path to the preload script)
¥Custom path to the preload script
如果你希望更改预加载脚本(和/或主线程文件)的位置,请编辑 /quasar.config
文件:
¥Should you wish to change the location of the preload script (and/or even the main thread file) then edit the /quasar.config
file:
// should you wish to change default files
sourceFiles: {
electronMain: 'src-electron/electron-main.js'
}