Ami*_*ani 66 javascript node.js electron
我正在尝试fs在我的renderer流程中使用 Node 模块(在本例中为),如下所示:
// main_window.js
const fs = require('fs')
function action() {
console.log(fs)
}
Run Code Online (Sandbox Code Playgroud)
注意:action当我按下main_window.
但这给出了一个错误:
Uncaught ReferenceError: require is not defined
at main_window.js:1
Run Code Online (Sandbox Code Playgroud)
我可以解决这个问题,正如这个接受的答案所建议的那样,通过main.js在初始化时将这些行添加到我的main_window:
// main.js
main_window = new BrowserWindow({
width: 650,
height: 550,
webPreferences: {
nodeIntegration: true
}
})
Run Code Online (Sandbox Code Playgroud)
但是,根据 docs,这不是最好的做法,我应该创建一个preload.js文件并在那里加载这些 Node 模块,然后在我的所有renderer进程中使用它。像这样:
main.js:
main_window = new BrowserWindow({
width: 650,
height: 550,
webPreferences: {
preload: path.join(app.getAppPath(), 'preload.js')
}
})
Run Code Online (Sandbox Code Playgroud)
preload.js:
const fs = require('fs')
window.test = function() {
console.log(fs)
}
Run Code Online (Sandbox Code Playgroud)
main_window.js:
function action() {
window.test()
}
Run Code Online (Sandbox Code Playgroud)
它有效!
现在我的问题是,我应该将我的renderer进程的大部分代码编写在preload.js(因为只有在preload.js我可以访问 Node 模块中)然后只调用每个renderer.js文件中的函数(例如这里,main_window.js) ? 我在这里不明白什么?
Zac*_*Zac 83
正如另一位用户所问,让我在下面解释我的答案。
preload.js在 Electron 中使用 的正确方法是在您的应用程序可能需要的任何模块周围公开列入白名单的包装器require。
在安全方面,暴露require或您通过require调用中检索到的任何内容都是危险的preload.js(请参阅我的评论以获取更多解释原因)。如果您的应用加载远程内容(很多人都会这样做),则尤其如此。
为了做正确的事情,您需要在您的设备上启用许多选项,BrowserWindow如下所述。设置这些选项会强制您的电子应用程序通过 IPC(进程间通信)进行通信,并将两个环境彼此隔离。像这样设置您的应用程序允许您验证任何可能是require后端中的“d 模块”的内容,而客户端不会对其进行篡改。
下面,您将找到一个简短的示例,说明我所说的内容以及它在您的应用程序中的外观。如果您刚开始,我可能会建议您使用secure-electron-template(我是其作者)在构建电子应用程序时从一开始就融入了所有这些安全最佳实践。
此页面还提供了有关使用 preload.js 制作安全应用程序所需的架构的详细信息。
主文件
const {
app,
BrowserWindow,
ipcMain
} = require("electron");
const path = require("path");
const fs = require("fs");
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win;
async function createWindow() {
// Create the browser window.
win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: false, // is default value after Electron v5
contextIsolation: true, // protect against prototype pollution
enableRemoteModule: false, // turn off remote
preload: path.join(__dirname, "preload.js") // use a preload script
}
});
// Load app
win.loadFile(path.join(__dirname, "dist/index.html"));
// rest of code..
}
app.on("ready", createWindow);
ipcMain.on("toMain", (event, args) => {
fs.readFile("path/to/file", (error, data) => {
// Do something with file contents
// Send result back to renderer process
win.webContents.send("fromMain", responseObj);
});
});
Run Code Online (Sandbox Code Playgroud)
预加载.js
const {
contextBridge,
ipcRenderer
} = require("electron");
// Expose protected methods that allow the renderer process to use
// the ipcRenderer without exposing the entire object
contextBridge.exposeInMainWorld(
"api", {
send: (channel, data) => {
// whitelist channels
let validChannels = ["toMain"];
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, data);
}
},
receive: (channel, func) => {
let validChannels = ["fromMain"];
if (validChannels.includes(channel)) {
// Deliberately strip event as it includes `sender`
ipcRenderer.on(channel, (event, ...args) => func(...args));
}
}
}
);
Run Code Online (Sandbox Code Playgroud)
索引.html
<!doctype html>
<html lang="en-US">
<head>
<meta charset="utf-8"/>
<title>Title</title>
</head>
<body>
<script>
window.api.receive("fromMain", (data) => {
console.log(`Received ${data} from main process`);
});
window.api.send("toMain", "some data");
</script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
Abe*_*ejo 34
并非官方文档中的所有内容都可以在代码中的任何位置直接实现。您必须需要对环境和流程有简明的了解。
| 环境/过程 | 描述 |
|---|---|
| 主要的 | API 更接近操作系统(低级)。其中包括文件系统、基于操作系统的通知弹出窗口、任务栏等。这些是通过 Electron 的核心 API 和 Node.js 的组合实现的 |
| 预载 | 最近的一个附录,旨在防止主环境中可用的强大 API 泄露。有关更多详细信息,请参阅Electron v12 变更日志和问题 #23506。 |
| 渲染器 | 现代 Web 浏览器的 API,例如 DOM 和前端 JavaScript(高级)。这是通过 Chromium 实现的。 |
| 设想 | contextIsolation |
nodeIntegration |
评论 |
|---|---|---|---|
| A | false |
false |
不需要预载。Node.js 在 Main 中可用,但在 Renderer 中不可用。 |
| 乙 | false |
true |
不需要预载。Node.js 在 Main 和 Renderer 中可用。 |
| C | true |
false |
需要预加载。Node.js 在主加载和预加载中可用,但在渲染器中不可用。默认。受到推崇的。 |
| D | true |
true |
需要预加载。Node.js 在 Main、Preload 和 Renderer 中可用。 |
您必须使用 Electron 的进程间通信(IPC)才能使主进程和渲染进程进行通信。
BrowserWindow.webContents.send()向 Renderer 发送消息的方法ipcMain.handle()从Renderer接收消息的方法主要的
/**
* Sending messages to Renderer
* `window` is an object which is an instance of `BrowserWindow`
* `data` can be a boolean, number, string, object, or array
*/
window.webContents.send( 'custom-endpoint', data );
/**
* Receiving messages from Renderer
*/
ipcMain.handle( 'custom-endpoint', async ( event, data ) => {
console.log( data )
} )
Run Code Online (Sandbox Code Playgroud)
预载
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld( 'api', {
send: ( channel, data ) => ipcRenderer.invoke( channel, data ),
handle: ( channel, callable, event, data ) => ipcRenderer.on( channel, callable( event, data ) )
} )
Run Code Online (Sandbox Code Playgroud)
渲染器
/**
* Sending messages to Main
* `data` can be a boolean, number, string, object, or array
*/
api.send( 'custom-endpoint', data )
/**
* Receiving messages from Main
*/
api.handle( 'custom-endpoint', ( event, data ) => function( event, data ) {
console.log( data )
}, event);
Run Code Online (Sandbox Code Playgroud)
尽可能遵守对相同流程/环境的承诺。你对main 的承诺应该留在 main 上。你对渲染器的承诺也应该留在渲染器上。不要做出从主程序跳转到预加载程序再到渲染器的承诺。
您的大部分业务逻辑仍应位于主端或渲染器端,但绝不应位于预加载端。这是因为预载几乎只是作为一种媒介而存在。预载应该非常小。
在OP的情况下,fs应该在主端实现。
小智 8
Electron 的事情进展很快,引起了一些混乱。最新的惯用例子(在我咬牙切齿后所能确定的最好的情况)是:
主文件
app.whenReady().then(() => {`
let mainWindow = new BrowserWindow({`
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true
},
width:640,
height: 480,
resizable: false
})
... rest of code
Run Code Online (Sandbox Code Playgroud)
预加载.js
const { contextBridge, ipcRenderer} = require('electron')
contextBridge.exposeInMainWorld(
'electron',
{
sendMessage: () => ipcRenderer.send('countdown-start')
}
)
Run Code Online (Sandbox Code Playgroud)
渲染器.js
document.getElementById('start').addEventListener('click', _ => {
window.electron.sendMessage()
})
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
41220 次 |
| 最近记录: |