记录一次 Vite CSS热重载失效踩坑经历
结论
文章较长,给赶时间的同学先说结论
排查自己代码和所用包代码中的document.head.innerHTML+=""
代码
背景
本人在使用vite+vue3+pug+tailwindcss开发一个博客前端页面, 直到佛系的我时隔大概一个月再次打开这个项目准备继续写的时候忽然发现好像vite的css热重载失效了(html,js的热重载是对的)
分析过程
vite采用HMR的方式进行热重载, 具体表现为使用WebSocket
进行接受变更
文件中的css代码更新后会,浏览器接收到如下信息
{
"type": "update",
"updates": [
{
"type": "js-update",
"timestamp": 1639711706402,
"path": "/src/views/Home.vue?vue&type=style&index=0&lang.css",
"acceptedPath": "/src/views/Home.vue?vue&type=style&index=0&lang.css"
}
]
}
并且会重新请求一个文件
可以在这个文件中发现, 主要代码为从/@vite/client文件中的updateStyle
大家应该都知道, 可以直接在sources中的文件里面修改代码或者打断点进行调试的, 直接给358行打上断点看看究竟是哪里出问题了
打好断点之后刷新页面看看sheetsMap中存放的到底是什么,不难发现里面存放的是key加上对应的style标签,并且该style标签如果单机的话是可以跳转到对应的dom节点上去的(这也就说明该标签还是正常被引用的)
接下来全部过掉所有的断点,单独去修改一下文件,看看这个时候发生了什么,注意前面说的,在sources里面是可以修改代码进行调试的
首先修改clent.ts添加两行代码,然后去文件中修改vue文件的css
修改文件后果不其然又调用了updateStyle方法, 这次可以发现style确实是有实例的, 但是parentNode却为null, 回头仔细翻找header中的style确实还在, 这就奇了怪了, 标签还在引用却丢失了
接下来开始终极debugger…删! copy一份项目出来, 从入口开始删, 看看究竟是哪里除了问题, 这个过程我没有持续很久,大概用了20分钟左右就定位到问题了, 一个看板娘插件
查看源码后最终定位到了问题document.head.innerHTML+=''
自己实测了一下确实是这个代码会引起标签引用失效
仔细想想也不难理解
document.head.innerHTML += "some code"
// 等价于
document.head.innerHTML = document.head.innerHTML + "some code"
// innerHTML拿到的是字符串,所以会导致head中所有元素被覆盖 之前获取的引用也就丢失了