Laravel Mix使用Glide.js为何需要给script添加type=module属性?
问题原因及解答
核心结论
type="module" 不是Laravel Mix搭配import语法的必填属性,你遇到的问题本质是JS执行时机早于DOM节点渲染,type="module" 只是刚好通过自身的延迟执行特性解决了执行顺序问题。
具体原理
- 普通不带特殊属性的
<script>标签:浏览器解析到标签时会立即下载并执行代码,如果你的script标签放在轮播DOM结构(.glide节点)之前,执行时目标节点还没有被渲染到页面上,Glide初始化找不到对应元素就会抛出Root element must be a existing Html node警告。 type="module"标签:浏览器会将其识别为ES模块,默认自带defer加载效果,会等整个HTML DOM树完全解析完成后再执行代码,此时轮播节点已经存在,所以初始化成功。
其他替代方案(无需加type="module")
如果你不想使用type="module",可以选择任意一种方案解决问题:
- 调整script标签位置,放在页面
</body>结束标签之前,保证执行时所有DOM已经渲染完成 - 给普通script标签添加
defer属性,实现和ES模块一样的延迟执行效果:
<script src="{{ mix('js/app.js') }}" defer></script>
- 改造JS初始化逻辑,等到DOM加载完成后再初始化Glide:
// resources/js/app.js require('./bootstrap'); import Glide from '@glidejs/glide' document.addEventListener('DOMContentLoaded', () => { const glideEl = document.querySelector('.glide') if (glideEl) { new Glide(glideEl).mount() } })
什么时候才必须加type="module"?
只有当你不使用打包工具,直接在浏览器中运行原生ES模块、靠浏览器本身处理import语法加载其他模块时,才必须给script标签添加该属性,否则浏览器会将import识别为非法语法报错。你当前使用Laravel Mix已经将所有ES模块语法转译打包成了兼容的单文件JS,不需要依赖浏览器处理模块加载,因此type="module"不是必填项。
内容的提问来源于stack exchange,提问作者Torben
相关产品推荐
相关产品推荐

