预加载脚本
什么是预加载脚本?
Electron 的主进程是一个拥有着完全操作系统访问权限的 Node.js 环境, 另一方面,出于安全原因,渲染进程默认跑在网页页面上,而并非 Node.js里。
为了将 Electron 的不同类型的进程桥接在一起,我们需要使用被称为
预加载
的特殊脚本。
使用预加载脚本来增强渲染器
BrowserWindow 的预加载脚本运行在具有 HTML DOM
和 Node.js
、Electron API
的有限子集访问权限的环境中。
预加载脚本沙盒化
从 Electron 20 开始,预加载脚本默认 沙盒化 ,不再拥有完整 Node.js 环境的访问权。 实际上,这意味着你只拥有一个 polyfilled 的 require 函数,这个函数只能访问一组有限的 API。
可用的API | 详细信息 |
---|---|
Electron 模块 | 渲染进程模块 |
Node.js 模块 | events、timers、url |
Polyfilled 的全局模块 | Buffer, process, clearImmediate, setImmediate |
与 Chrome 扩展的内容脚本(Content Script)类似,预加载脚本在渲染器加载网页之前注入。
演示
创建一个将应用中的 Chrome、Node、Electron 版本号暴露至渲染器的预加载脚本
preload.js
const { contextBridge } = require('electron')
contextBridge.exposeInMainWorld('versions', {
node: () => process.versions.node,
chrome: () => process.versions.chrome,
electron: () => process.versions.electron
// 除函数之外,我们也可以暴露变量
})
为了将脚本附在渲染进程上,在 BrowserWindow
构造器中使用 webPreferences.preload
传入脚本的路径。
main.js
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
在进程之间通信
Electron 的主进程和渲染进程有着清楚的分工并且不可互换。 这代表着无论是从渲染进程直接访问 Node.js 接口,亦或者是从主进程访问 HTML 文档对象模型 (DOM),都是不可能的。
解决这一问题的方法是使用进程间通信 (IPC)。可以使用 Electron 的 ipcMain 模块和 ipcRenderer 模块来进行进程间通信。 为了从你的网页向主进程发送消息,你可以使用 ipcMain.handle 设置一个主进程处理程序(handler),然后在预处理脚本中暴露一个被称为 ipcRenderer.invoke 的函数来触发该处理程序(handler)。
首先,在预处理脚本中设置 invoke 调用
preload.js
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('versions', {
node: () => process.versions.node,
chrome: () => process.versions.chrome,
electron: () => process.versions.electron,
ping: () => ipcRenderer.invoke('ping')
// 除函数之外,我们也可以暴露变量
})
然后,在主进程中设置你的 handle 监听器。 我们在 HTML 文件加载_之前_完成了这些,所以才能保证在你从渲染器发送 invoke 调用之前处理程序能够准备就绪。
const { app, BrowserWindow, ipcMain } = require('electron/main')
const path = require('node:path')
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
win.loadFile('index.html')
}
app.whenReady().then(() => {
ipcMain.handle('ping', () => 'pong')
createWindow()
})
将发送器与接收器设置完成之后,现在你可以将信息通过刚刚定义的 'ping' 通道从渲染器发送至主进程当中。
renderer.js
const func = async () => {
const response = await window.versions.ping()
console.log(response) // 打印 'pong'
}
func()
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现