Electron Renderer 多 HTML 页面打包与加载实战指南

老萱君_7113

老萱君_7113

2026-11-13

542人浏览

原创

Electron Renderer 多 HTML 页面打包与加载实战指南

本文详解 Electron-Vite 项目中多 HTML 入口(如 index.html 和 video.html)在生产环境白屏或报错“Not allowed to load local resource”问题的根因与完整解决方案,涵盖 Vite 构建配置、路径解析、安全策略适配及 IPC 通信修复要点。

本文详解 electron-vite 项目中多 html 入口(如 `index.html` 和 `video.html`)在生产环境白屏或报错“not allowed to load local resource”问题的根因与完整解决方案,涵盖 vite 构建配置、路径解析、安全策略适配及 ipc 通信修复要点。

在 Electron-Vite + React 项目中,开发者常误以为只要 index.html 能正常加载,其他 HTML 文件(如 video.html)也能通过 loadFile() 直接打开——但实际在生产构建后,Vite 默认仅将 src/renderer/index.html 作为唯一入口进行打包和资源注入,导致 video.html 及其关联的 JS/CSS 资源未被构建、未被复制到输出目录(如 out/renderer/),最终 loadFile() 尝试加载一个“不存在的文件”,触发 Chromium 的 Not allowed to load local resource 错误。

✅ 正确做法:显式声明多 HTML 入口

Vite 的 build.rollupOptions.input 支持对象语法,可为每个 HTML 页面指定独立入口。需在 electron.vite.config.js 中明确注册 video.html:

// electron.vite.config.js
import { resolve } from 'path'
import { defineConfig, externalizeDepsPlugin } from 'electron-vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  main: {
    plugins: [externalizeDepsPlugin()]
  },
  preload: {
    plugins: [externalizeDepsPlugin()]
  },
  renderer: {
    build: {
      rollupOptions: {
        // 关键配置:声明多个 HTML 入口
        input: {
          index: resolve(__dirname, 'src/renderer/index.html'),
          video: resolve(__dirname, 'src/renderer/video.html')
        }
      }
    },
    resolve: {
      alias: {
        '@renderer': resolve('src/renderer/src')
      }
    },
    plugins: [react()]
  }
})

? 为什么必须这样?
Electron-Vite 的 renderer 构建阶段本质是运行一次 Vite 构建。默认 input: 'src/renderer/index.html' 意味着只有该文件及其 <script type="module"></script> 引用链会被处理、转译、哈希重命名并输出到 out/renderer/。而 video.html 若未声明,则不会生成对应产物(如 out/renderer/video-CxYz1234.html),loadFile() 自然失败。

✅ 构建后路径验证与加载逻辑优化

构建完成后,检查 out/renderer/ 目录是否生成了两个 HTML 文件(如 index.html 和 video-xxxxx.html)。此时 loadFile() 必须指向构建后的绝对路径,而非开发时的源路径:

// main/index.js(生产环境加载逻辑)
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
  // 开发:走 dev server(http://localhost:5173/video.html)
  secondWindow.loadURL(`${process.env['ELECTRON_RENDERER_URL']}/video.html`)
} else {
  // 生产:必须使用 join(__dirname, '../renderer/video.html') —— 
  // 注意:此处的 '../renderer/video.html' 是构建后相对路径,
  // 实际由 Vite 输出到 out/renderer/ 下,electron-builder 会自动拷贝
  secondWindow.loadFile(join(__dirname, '../renderer/video.html'))
}

⚠️ 重要提醒:loadFile() 的路径是相对于 app.getAppPath()(即主进程所在目录),而 electron-builder 打包时会将 out/renderer/ 内容复制到 dist/ 或 resources/app.asar/renderer/。因此确保 electron-builder 配置中 files 字段包含 renderer/**/*(默认已包含)。

? 安全策略兼容性检查

你的 webPreferences 启用了 webSecurity: true(默认值),这是推荐的安全实践。但需注意:

  • loadFile() 加载本地 HTML 时,Chromium 会启用严格的同源策略(file:// 协议),禁止跨目录请求资源(如 fetch('../public/data.json'));
  • 若 video.html 中需加载本地 JSON、调用 Node API 或读取文件,必须通过 preload 脚本桥接,严禁在渲染进程中直接使用 fs 或 require;
  • 确保 preload/index.js 中正确暴露所需能力,并在 video.html 的 <script></script> 中通过 window.electron.* 调用(需配合 contextIsolation: true 的 contextBridge 机制)。

示例 preload/index.js 片段:

DeepBI DHTML 页面生成器
DeepBI DHTML 页面生成器

生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur

下载
// preload/index.js
import { contextBridge, ipcRenderer } from 'electron'

contextBridge.exposeInMainWorld('electron', {
  // 仅暴露必要方法
  startVideo: (path) => ipcRenderer.invoke('play-video', path),
  onVideoReady: (callback) => ipcRenderer.on('start-video', callback)
})

? IPC 通信断裂的修复要点

原文提到“IPC 通信在修改配置后中断”,常见原因有三:

  1. 事件监听时机错位:video.html 对应的 React 应用(video.jsx)可能在 secondWindow 创建后才初始化,而 ipcMain.on('play-video') 已注册。需确保 video.html 加载完成、React 渲染完毕后再发送消息:

    // 在 video.jsx 中
    useEffect(() => {
      window.electron.onVideoReady((event, videoPath) => {
        // 播放逻辑
      })
    }, [])
  2. 窗口引用失效:secondWindow 可能被 GC 或关闭,ipcMain 发送时未校验:

    ipcMain.on("play-video", (event, videoPath) => {
      if (secondWindow && !secondWindow.isDestroyed()) {
        secondWindow.webContents.send("start-video", videoPath)
      }
    })
  3. ASAR 打包路径问题:若 video.html 中硬编码了 ../public/xxx.json,在 ASAR 包内路径会变为 app.asar/public/xxx.json,需用 app.getAppPath() + join() 动态拼接,或改用 fetch('public/xxx.json')(Vite 会自动处理 public 目录)。

✅ 总结:四步闭环排查清单

步骤 检查项 工具/命令
1. 构建产物 out/renderer/ 下是否存在 video-*.html? ls out/renderer/ \| grep video
2. 路径加载 secondWindow.loadFile(...) 是否指向构建后路径? console.log(join(__dirname, '../renderer/video.html'))
3. 安全上下文 video.html 是否通过 preload 调用 Node API?是否禁用 eval? 检查 DevTools → Application → Frames
4. IPC 生命周期 secondWindow 是否存活?事件监听是否在组件挂载后注册? console.log(secondWindow?.isDestroyed())

遵循以上方案,即可彻底解决 Electron-Vite 多 HTML 页面在生产环境的加载失败问题,在保持高安全性(contextIsolation: true, webSecurity: true)前提下,实现主窗口与视频窗口的稳定协同。

前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!

相关文章

HTML速学教程(入门课程)
HTML速学教程(入门课程)

HTML怎么学习?HTML怎么入门?HTML在哪学?HTML怎么学才快?不用担心,这里为大家提供了HTML速学教程(入门课程),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

html

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
js获取数组长度的方法
js获取数组长度的方法

在js中,可以利用array对象的length属性来获取数组长度,该属性可设置或返回数组中元素的数目,只需要使用“array.length”语句即可返回表示数组对象的元素个数的数值,也就是长度值。php中文网还提供JavaScript数组的相关下载、相关课程等内容,供大家免费下载使用。

2023.06.20

5846

5

js刷新当前页面
js刷新当前页面

js刷新当前页面的方法:1、reload方法,该方法强迫浏览器刷新当前页面,语法为“location.reload([bForceGet]) ”;2、replace方法,该方法通过指定URL替换当前缓存在历史里(客户端)的项目,因此当使用replace方法之后,不能通过“前进”和“后退”来访问已经被替换的URL,语法为“location.replace(URL) ”。php中文网为大家带来了js刷新当前页面的相关知识、以及相关文章等内容

2023.07.04

1409

3

js四舍五入
js四舍五入

js四舍五入的方法:1、tofixed方法,可把 Number 四舍五入为指定小数位数的数字;2、round() 方法,可把一个数字舍入为最接近的整数。php中文网为大家带来了js四舍五入的相关知识、以及相关文章等内容

2023.07.04

5764

6

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

2023.09.01

1060

4

JavaScript转义字符
JavaScript转义字符

JavaScript中的转义字符是反斜杠和引号,可以在字符串中表示特殊字符或改变字符的含义。本专题为大家提供转义字符相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.04

2036

5

js生成随机数的方法
js生成随机数的方法

js生成随机数的方法有:1、使用random函数生成0-1之间的随机数;2、使用random函数和特定范围来生成随机整数;3、使用random函数和round函数生成0-99之间的随机整数;4、使用random函数和其他函数生成更复杂的随机数;5、使用random函数和其他函数生成范围内的随机小数;6、使用random函数和其他函数生成范围内的随机整数或小数。

2023.09.04

3985

4

如何启用JavaScript
如何启用JavaScript

JavaScript启用方法有内联脚本、内部脚本、外部脚本和异步加载。详细介绍:1、内联脚本是将JavaScript代码直接嵌入到HTML标签中;2、内部脚本是将JavaScript代码放置在HTML文件的`<script>`标签中;3、外部脚本是将JavaScript代码放置在一个独立的文件;4、外部脚本是将JavaScript代码放置在一个独立的文件。

2023.09.12

5273

6

Js中Symbol类详解
Js中Symbol类详解

javascript中的Symbol数据类型是一种基本数据类型,用于表示独一无二的值。Symbol的特点:1、独一无二,每个Symbol值都是唯一的,不会与其他任何值相等;2、不可变性,Symbol值一旦创建,就不能修改或者重新赋值;3、隐藏性,Symbol值不会被隐式转换为其他类型;4、无法枚举,Symbol值作为对象的属性名时,默认是不可枚举的。

2023.09.20

3460

5

java访问控制修饰符介绍
java访问控制修饰符介绍

java访问控制修饰符有四种,分别是public、protected、private、默认访问修饰符。详细介绍:1、public,public是最宽松的访问控制修饰符,被修饰的类、方法和变量可以被任何其他类访问,当一个类、方法或变量被声明为public时,它们可以在任何地方被访问,无论是同一个包中的类还是不同包中的类;2、protected修饰符等等。

2023.09.20

1108

7

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
GDB 17.2 官方文档集合
GDB 17.2 官方文档集合

共0课时 | 0人学习

Bootstrap 入门安装配置
Bootstrap 入门安装配置

共0课时 | 0人学习

38+ PhpStorm 提示和技巧
38+ PhpStorm 提示和技巧

共1课时 | 239人学习