Vite搭配Rails使用Vue自定义元素时页面无限重载、调用栈溢出如何解决
问题根源
无限重载是Vite热更新(HMR)机制和原生自定义元素注册规则冲突导致的:
- 原生
CustomElementRegistry不允许重复注册同一个标签名,重复调用define方法会直接抛出运行时错误 - Vite HMR触发模块更新时,会重新执行对应入口文件的全部代码,未加重复注册判断的情况下,每次热更新都会重新执行
window.customElements.define('panel-custom', CustomElement),抛出注册冲突错误 - Vite检测到页面存在未捕获的运行时错误时,会触发全页重载兜底,重载后代码又再次执行重复注册逻辑,由此进入死循环
解决方案
1. 新增自定义元素注册前置判断(优先方案,不影响HMR使用)
修改入口文件的注册逻辑,注册前先判断对应标签是否已经被注册过,避免重复执行注册逻辑:
import { defineCustomElement } from 'vue'; import Panel from '~/components/panel_custom/Panel.ce.vue'; const CustomElement = defineCustomElement(Panel); // 新增注册前判断,避免重复注册 if (!window.customElements.get('panel-custom')) { window.customElements.define('panel-custom', CustomElement); }
这个方案可以直接解决注册冲突导致的重载问题,同时完整保留Vite HMR能力,.ce.vue组件的代码变更依然可以正常触发热更新。
2. 辅助排查项
如果做完上述修改后依然存在重载问题,可以检查以下配置:
- 确认
vite.config.js中HMR的host、port配置和Vite开发服务器的实际启动参数一致,避免HMR WebSocket连接失败触发的全页重载 - 确认ERB模板中没有重复引入同一个Vite入口JS文件,重复引入也会导致注册逻辑执行多次
你之前关闭HMR的方案相当于直接规避了模块重执行的场景,虽然能解决问题但会大幅降低开发效率,优先使用上述注册判断的方案即可。
内容的提问来源于stack exchange,提问作者user16732355
相关产品推荐
相关产品推荐

