在 Electron 中正确利用 preload.js:综合指南
P粉197639753
2023-08-27 20:25:30
<p>我尝试在我的 <code>renderer</code> 进程中使用节点模块(在本例中为 <code>fs</code>),如下所示:</p>
<pre class="brush:php;toolbar:false;">// main_window.js
const fs = require('fs')
function action() {
console.log(fs)
}</pre>
<p><sup>注意:当我按下 <code>main_window</code> 中的按钮时,会调用 <code>action</code> 函数。</sup></p>
<p>但这会产生错误:</p>
<pre class="brush:php;toolbar:false;">Uncaught ReferenceError: require is not defined
at main_window.js:1</pre>
<p>我可以解决这个问题,正如这个接受的答案所建议的,通过在初始化 <code>main_window</code> 时将这些行添加到我的 <code>main.js</code> 中:</p>
<pre class="brush:php;toolbar:false;">// main.js
main_window = new BrowserWindow({
width: 650,
height: 550,
webPreferences: {
nodeIntegration: true
}
})</pre>
但是,根据文档,这不是最好的做法,我应该创建一个 <code>preload.js</code> 文件并在其中加载这些 Node 模块,然后在我的所有 <code>renderer</code> 中使用它流程。像这样:<p><br /></p>
<p><code>main.js</code>:</p>
<pre class="brush:php;toolbar:false;">main_window = new BrowserWindow({
width: 650,
height: 550,
webPreferences: {
preload: path.join(app.getAppPath(), 'preload.js')
}
})</pre>
<p><code>preload.js</code>:</p>
<pre class="brush:php;toolbar:false;">const fs = require('fs')
window.test = function() {
console.log(fs)
}</pre>
<p><code>main_window.js</code>:</p>
<pre class="brush:php;toolbar:false;">function action() {
window.test()
}</pre>
<p>而且它有效!</p>
<hr />
<p>现在我的问题是,我应该在 <code>preload.js</code> 中编写 <code>renderer</code> 进程的大部分代码,这不是违反直觉的吗(因为只有在 <code>preload.js</code> 中我才能访问 Node 模块)然后仅调用每个 <code>renderer.js</code> 文件中的函数(例如此处,<code>main_window.js</code>)?我在这里不明白什么? </p>
考虑这个例子
并非官方文档中的所有内容都可以在代码中的任何位置直接实现。您必须需要对环境和流程有简明的了解。
上下文隔离和节点集成
contextIsolation
nodeIntegration
假
假
假
true
true
假
true
true
如何正确使用预载?
您必须使用 Electron 的进程间通信 (IPC) 才能使主进程和渲染进程进行通信。
BrowserWindow.webContents.send() code>
向渲染器发送消息的方法ipcMain.handle()
从渲染器接收消息的方法实现示例
主要
预加载
渲染器
使用 Promise 怎么样?
尽可能遵守对相同流程/环境的承诺。您在 main 上的承诺应该保留在 main 上。您对渲染器的承诺也应该保留在渲染器上。不要做出从主程序跳转到预加载程序再到渲染器的承诺。
文件系统
您的大部分业务逻辑仍应位于主端或渲染器端,但绝不应位于预加载中。这是因为预载几乎只是作为一种媒介而存在。预载应该非常小。
在OP的情况下,
fs
应该在主端实现。编辑 2022 年
我已经发表了一篇关于 Electron 历史的较大文章( Electron 版本中的安全性如何发生变化)以及 Electron 开发人员可以采取的其他安全注意事项,以确保在新应用程序中正确使用预加载文件。
编辑 2020
正如另一位用户所问,让我在下面解释我的答案。
在 Electron 中使用
preload.js
的正确方法是在您的应用可能需要require
的任何模块周围公开白名单包装器。从安全角度来看,公开
require
或通过preload.js
中的require
调用检索的任何内容都是危险的(请参阅我的评论以获取更多解释原因)。如果您的应用程序加载远程内容(许多应用程序都会这样做),则尤其如此。为了正确执行操作,您需要在 BrowserWindow 正如我在下面详细介绍的。设置这些选项会强制您的电子应用程序通过 IPC(进程间通信)进行通信,并将两个环境相互隔离。像这样设置您的应用程序可以让您验证后端中可能是
require
模块的任何内容,而客户端不会对其进行篡改。下面,您将找到一个简短的示例,介绍我所讨论的内容以及它在您的应用中的外观。如果您是新手,我可能建议使用
secure-electron-template
(我是其作者)在构建电子应用程序时从一开始就融入了所有这些安全最佳实践。此页面也有很好的信息使用 preload.js 制作安全应用程序时所需的架构。
main.js
preload.js
index.html