Electron通过预加载脚本从渲染器访问Node.js

2024-03-04 07:04

本文主要是介绍Electron通过预加载脚本从渲染器访问Node.js,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

问题:如何实现输出Electron的版本号和它的依赖项到你的web页面上?

答案:在主进程通过Node的全局 process 对象访问这个信息是微不足道的。 然而,你不能直接在主进程中编辑DOM,因为它无法访问渲染器 文档 上下文。 它们存在于完全不同的进程!这是将 预加载 脚本连接到渲染器时派上用场的地方。预加载脚本在渲染器进程加载之前加载,并有权访问两个 渲染器全局 (例如 window 和 document) 和 Node.js 环境。

1.创建预加载脚本 

在项目的src/preload/目录下创建一个名为 preload.js 的新脚本如下: 

const { contextBridge, ipcRenderer } = require('electron')contextBridge.exposeInMainWorld('electronAPI', {onUpdateCounter: (callback) => ipcRenderer.on('update-counter', (_event, value) => callback(value)),setTitle: (title) => ipcRenderer.send('set-title', title)
})

2.在主进程中引入

在主进程的background.js文件中,引入预加载脚本如下:

 // 指定预加载脚本webPreferences: {// 启用上下文隔离contextIsolation: true,// 禁用 Node.js 集成,因为我们将通过预加载脚本来提供所需的功能nodeIntegration: false,// 禁用 remote 模块,出于安全考虑enableRemoteModule: false,// 设置预加载脚本preload: path.join(__dirname, "preload.js"),},

这里使用了两个Node.js概念:

  • __dirname 字符串指向当前正在执行脚本的路径 (在本例中,它指向你的项目的根文件夹)。
  • path.join API 将多个路径联结在一起,创建一个跨平台的路径字符串。

我们使用一个相对当前正在执行JavaScript文件的路径,这样您的相对路径将在开发模式和打包模式中都将有效。

background.js文件 

'use strict'import { app, protocol, BrowserWindow, ipcMain, Menu } from 'electron'
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
// import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
const isDevelopment = process.env.NODE_ENV !== 'production'
const path = require('path')
// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([{ scheme: 'app', privileges: { secure: true, standard: true } }
])async function createWindow() {// Create the browser window.const win = new BrowserWindow({width: 800,height: 600,// 指定预加载脚本webPreferences: {// 启用上下文隔离contextIsolation: true,// 禁用 Node.js 集成,因为我们将通过预加载脚本来提供所需的功能nodeIntegration: false,// 禁用 remote 模块,出于安全考虑enableRemoteModule: false,// 设置预加载脚本preload: path.join(__dirname, "preload.js"),},// webPreferences: {//   // Use pluginOptions.nodeIntegration, leave this alone//   // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info//   nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,//   contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION// }})///ipcMain.on('set-title', (event, title) => {const webContents = event.senderconsole.log(`接收到渲染进程消息:`, title);event.reply('update-counter', title)})console.log(`path.join(__dirname, "preload.js")`, path.join(__dirname, "preload.js"));///if (process.env.WEBPACK_DEV_SERVER_URL) {// Load the url of the dev server if in development modeawait win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)if (!process.env.IS_TEST) win.webContents.openDevTools()} else {createProtocol('app')// Load the index.html when not in developmentwin.loadURL('app://./index.html')}
}// Quit when all windows are closed.
app.on('window-all-closed', () => {// On macOS it is common for applications and their menu bar// to stay active until the user quits explicitly with Cmd + Qif (process.platform !== 'darwin') {app.quit()}
})app.on('activate', () => {// On macOS it's common to re-create a window in the app when the// dock icon is clicked and there are no other windows open.if (BrowserWindow.getAllWindows().length === 0) createWindow()
})// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', async () => {// if (isDevelopment && !process.env.IS_TEST) {//   // Install Vue Devtools//   try {//     //await installExtension(VUEJS_DEVTOOLS)//   } catch (e) {//     console.error('Vue Devtools failed to install:', e.toString())//   }// }createWindow()
})// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {if (process.platform === 'win32') {process.on('message', (data) => {if (data === 'graceful-exit') {app.quit()}})} else {process.on('SIGTERM', () => {app.quit()})}
}

 3.在主进程和渲染进程中使用预加载脚本

主进程中使用:

 ipcMain.on('set-title', (event, title) => {const webContents = event.senderconsole.log(`接收到渲染进程消息:`, title);event.reply('update-counter', title)})

 主进程完整脚本文件

'use strict'import { app, protocol, BrowserWindow, ipcMain, Menu } from 'electron'
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
// import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
const isDevelopment = process.env.NODE_ENV !== 'production'
const path = require('path')
// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([{ scheme: 'app', privileges: { secure: true, standard: true } }
])async function createWindow() {// Create the browser window.const win = new BrowserWindow({width: 800,height: 600,// 指定预加载脚本webPreferences: {// 启用上下文隔离contextIsolation: true,// 禁用 Node.js 集成,因为我们将通过预加载脚本来提供所需的功能nodeIntegration: false,// 禁用 remote 模块,出于安全考虑enableRemoteModule: false,// 设置预加载脚本preload: path.join(__dirname, "preload.js"),},// webPreferences: {//   // Use pluginOptions.nodeIntegration, leave this alone//   // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info//   nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,//   contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION// }})///ipcMain.on('set-title', (event, title) => {const webContents = event.senderconsole.log(`接收到渲染进程消息:`, title);event.reply('update-counter', title)})console.log(`path.join(__dirname, "preload.js")`, path.join(__dirname, "preload.js"));///if (process.env.WEBPACK_DEV_SERVER_URL) {// Load the url of the dev server if in development modeawait win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)if (!process.env.IS_TEST) win.webContents.openDevTools()} else {createProtocol('app')// Load the index.html when not in developmentwin.loadURL('app://./index.html')}
}// Quit when all windows are closed.
app.on('window-all-closed', () => {// On macOS it is common for applications and their menu bar// to stay active until the user quits explicitly with Cmd + Qif (process.platform !== 'darwin') {app.quit()}
})app.on('activate', () => {// On macOS it's common to re-create a window in the app when the// dock icon is clicked and there are no other windows open.if (BrowserWindow.getAllWindows().length === 0) createWindow()
})// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', async () => {// if (isDevelopment && !process.env.IS_TEST) {//   // Install Vue Devtools//   try {//     //await installExtension(VUEJS_DEVTOOLS)//   } catch (e) {//     console.error('Vue Devtools failed to install:', e.toString())//   }// }createWindow()
})// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {if (process.platform === 'win32') {process.on('message', (data) => {if (data === 'graceful-exit') {app.quit()}})} else {process.on('SIGTERM', () => {app.quit()})}
}

渲染进程中使用:

<template><div><div>接收主进程的消息{{ ShowData }}</div><button @click="sendToMain">Send Message to Main</button></div>
</template><script>
export default {data() {return {ShowData: 0,};},methods: {sendToMain() {const title = Math.round(Math.random() * 100);window.electronAPI.setTitle(title);},},mounted() {// 监听主进程的回复window.electronAPI.onUpdateCounter((value) => {console.log(`接收主进程的消息:`, value);this.ShowData = value;});},//   beforeDestroy() {//     // 在组件销毁前,移除事件监听器//  window.ipcRenderer.removeAllListeners("reply-from-main");//   },
};
</script>

注意:开发环境时主进程使用的是软件编译后dist_electron目录下的preload.js 预加载文件

 到这里在开发环境就能使用预加载脚本实现主进程和渲染进程通信了

4.在vue.config.js中进行electron打包配置

如果想在electron打包后的软件中仍然可以正常使用预加载脚本文件的话,必须在vue.config.js文件中进行相应的打包配置。

  pluginOptions: {electronBuilder: {removeElectronJunk: false,preload: './src/preload/preload.js',builderOptions: {"appId": "voloday_test","productName": "voloday_test",//项目名,也是生成的安装文件名,即.exe"copyright": "Copyright © 2024",//版权信息"win": {//win相关配置// "icon": "./src/assets/icon.ico",//图标,当前图标在根目录下"target": [{"target": "nsis",//利用nsis制作安装程序"arch": ["x64",//64位]}]},"nsis": {"oneClick": false, // 是否一键安装"allowElevation": true, // 允许请求提升。 如果为false,则用户必须使用提升的权限重新启动安装程序。"allowToChangeInstallationDirectory": true, // 允许修改安装目录// "installerIcon": "./src/assets/icon.ico",// 安装图标// "uninstallerIcon": "./src/assets/icon.ico",//卸载图标// "installerHeaderIcon": "./src/assets/icon.ico", // 安装时头部图标"createDesktopShortcut": true, // 创建桌面图标"createStartMenuShortcut": true,// 创建开始菜单图标"shortcutName": "voloday_test", // 图标名称},}},},

vue.config.js文件 

const { defineConfig } = require('@vue/cli-service')
const path = require("path");
console.log(`path.join(__dirname,'preload.js')`, path.join(__dirname,'preload.js'));
module.exports = defineConfig({transpileDependencies: true,publicPath: './',pluginOptions: {electronBuilder: {removeElectronJunk: false,preload: './src/preload/preload.js',builderOptions: {"appId": "voloday_test","productName": "voloday_test",//项目名,也是生成的安装文件名,即.exe"copyright": "Copyright © 2024",//版权信息"win": {//win相关配置// "icon": "./src/assets/icon.ico",//图标,当前图标在根目录下"target": [{"target": "nsis",//利用nsis制作安装程序"arch": ["x64",//64位]}]},"nsis": {"oneClick": false, // 是否一键安装"allowElevation": true, // 允许请求提升。 如果为false,则用户必须使用提升的权限重新启动安装程序。"allowToChangeInstallationDirectory": true, // 允许修改安装目录// "installerIcon": "./src/assets/icon.ico",// 安装图标// "uninstallerIcon": "./src/assets/icon.ico",//卸载图标// "installerHeaderIcon": "./src/assets/icon.ico", // 安装时头部图标"createDesktopShortcut": true, // 创建桌面图标"createStartMenuShortcut": true,// 创建开始菜单图标"shortcutName": "voloday_test", // 图标名称},}},},})

源码:GitHub - 1t1824d/elctron29.0.0_node18.19.0_vuecli5.0.8_vue2 

这篇关于Electron通过预加载脚本从渲染器访问Node.js的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/772362

相关文章

Linux下MySQL数据库定时备份脚本与Crontab配置教学

《Linux下MySQL数据库定时备份脚本与Crontab配置教学》在生产环境中,数据库是核心资产之一,定期备份数据库可以有效防止意外数据丢失,本文将分享一份MySQL定时备份脚本,并讲解如何通过cr... 目录备份脚本详解脚本功能说明授权与可执行权限使用 Crontab 定时执行编辑 Crontab添加定

Three.js构建一个 3D 商品展示空间完整实战项目

《Three.js构建一个3D商品展示空间完整实战项目》Three.js是一个强大的JavaScript库,专用于在Web浏览器中创建3D图形,:本文主要介绍Three.js构建一个3D商品展... 目录引言项目核心技术1. 项目架构与资源组织2. 多模型切换、交互热点绑定3. 移动端适配与帧率优化4. 可

Java调用Python脚本实现HelloWorld的示例详解

《Java调用Python脚本实现HelloWorld的示例详解》作为程序员,我们经常会遇到需要在Java项目中调用Python脚本的场景,下面我们来看看如何从基础到进阶,一步步实现Java与Pyth... 目录一、环境准备二、基础调用:使用 Runtime.exec()2.1 实现步骤2.2 代码解析三、

Python脚本轻松实现检测麦克风功能

《Python脚本轻松实现检测麦克风功能》在进行音频处理或开发需要使用麦克风的应用程序时,确保麦克风功能正常是非常重要的,本文将介绍一个简单的Python脚本,能够帮助我们检测本地麦克风的功能,需要的... 目录轻松检测麦克风功能脚本介绍一、python环境准备二、代码解析三、使用方法四、知识扩展轻松检测麦

SpringBoot加载profile全面解析

《SpringBoot加载profile全面解析》SpringBoot的Profile机制通过多配置文件和注解实现环境隔离,支持开发、测试、生产等不同环境的灵活配置切换,无需修改代码,关键点包括配置文... 目录题目详细答案什么是 Profile配置 Profile使用application-{profil

通过配置nginx访问服务器静态资源的过程

《通过配置nginx访问服务器静态资源的过程》文章介绍了图片存储路径设置、Nginx服务器配置及通过http://192.168.206.170:8007/a.png访问图片的方法,涵盖图片管理与服务... 目录1.图片存储路径2.nginx配置3.访问图片方式总结1.图片存储路径2.nginx配置

基于Python Playwright进行前端性能测试的脚本实现

《基于PythonPlaywright进行前端性能测试的脚本实现》在当今Web应用开发中,性能优化是提升用户体验的关键因素之一,本文将介绍如何使用Playwright构建一个自动化性能测试工具,希望... 目录引言工具概述整体架构核心实现解析1. 浏览器初始化2. 性能数据收集3. 资源分析4. 关键性能指

shell脚本批量导出redis key-value方式

《shell脚本批量导出rediskey-value方式》为避免keys全量扫描导致Redis卡顿,可先通过dump.rdb备份文件在本地恢复,再使用scan命令渐进导出key-value,通过CN... 目录1 背景2 详细步骤2.1 本地docker启动Redis2.2 shell批量导出脚本3 附录总

Oracle数据库定时备份脚本方式(Linux)

《Oracle数据库定时备份脚本方式(Linux)》文章介绍Oracle数据库自动备份方案,包含主机备份传输与备机解压导入流程,强调需提前全量删除原库数据避免报错,并需配置无密传输、定时任务及验证脚本... 目录说明主机脚本备机上自动导库脚本整个自动备份oracle数据库的过程(建议全程用root用户)总结

Android Paging 分页加载库使用实践

《AndroidPaging分页加载库使用实践》AndroidPaging库是Jetpack组件的一部分,它提供了一套完整的解决方案来处理大型数据集的分页加载,本文将深入探讨Paging库... 目录前言一、Paging 库概述二、Paging 3 核心组件1. PagingSource2. Pager3.