预加载脚本

什么是预加载脚本?

Electron 的主进程是一个拥有着完全操作系统访问权限的 Node.js 环境, 另一方面,出于安全原因,渲染进程默认跑在网页页面上,而并非 Node.js里。

为了将 Electron 的不同类型的进程桥接在一起,我们需要使用被称为 预加载 的特殊脚本。

使用预加载脚本来增强渲染器

BrowserWindow 的预加载脚本运行在具有 HTML DOMNode.jsElectron 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()
posted @   暖暖De幸福  阅读(24)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示