写着写着,样式怎么突然全挂了?
今天聊一个让我差点砸键盘的坑。
事情是这样的,我在写一个 Vue 组件时,为了做点文本标记,在代码里随手加了几个类似引用标记的字符,大概长这样:
javascript
// unocss版本:0.39.3
<script setup>
// [citation:1][citation:3]
</script>
结果一保存,页面一刷新,好家伙,整个项目的 UnoCSS 样式全没了,页面直接"裸奔"。一开始我以为是 HMR(热更新)抽风,重启了 Vite 服务,甚至清了一遍 node_modules,问题依然稳如泰山。
这就有点意思了,难道是我写的某个 class 把全局样式给覆盖了?
顺藤摸瓜:去源码里抓"内鬼"
既然页面上没样式,我直接打开浏览器 DevTools 看网络请求,发现 UnoCSS 生成的那个 CSS 文件里,原本该有的 preflights(预设基础样式)和默认样式全都不翼而飞了。
为了搞清楚到底发生了什么,我去翻了下 Vite 内存中生成的 __vite__css 源码,结果看到了一段极其诡异的代码:
css
/* layer: preflights */
*,::before,::after{--un-rotate:0; ... /* 这里是一堆正常的 CSS 变量 */ ...}
/* layer: default */
.\[citation\:\]\[citation\:\]{citation:][citation:;}
.text-26px{font-size:26px;}
.font-bold{font-weight:700;}
看到 .\[citation\:\]\[citation\:\]{citation:][citation:;} 这一行,我瞬间明白了。
UnoCSS 把我写的 [citation:][citation:] 当成了 class 名去进行转义。但问题出在后面生成的 CSS 语法上------{citation:][citation:;} 这到底是什么鬼?大括号和方括号乱飞,完全不符合 CSS 的语法规范。
因为这段非法的 CSS 语法,浏览器的 CSS 解析器在解析到这儿的时候直接报错罢工。一颗老鼠屎坏了一锅粥,导致它后面的预设样式和正常 class 全都没能加载出来。
为什么 UnoCSS 会犯这种"低级错误"?
你可能会问,UnoCSS 这么成熟的工具,怎么会生成这种非法的 CSS?
这其实和原子化 CSS 工具的"贪婪扫描"机制有关。UnoCSS 在构建时,会用正则表达式去扫描你的源码(包括 template、script 甚至注释),提取所有可能是 class 名的字符串。
当它看到 [citation:1] 这种带方括号和冒号的写法时,它的正则匹配机制把它误认为了某种动态属性或者自定义的 utility class(比如 UnoCSS 支持的 [color:red] 这种任意值写法)。
在 0.39.3 这个版本里,解析器在处理这种边缘 case 时没做好兜底。它试图把 [citation:][citation:] 解析成 CSS 规则,但在拼接大括号和属性值的时候逻辑崩了,最终输出了那段语法错误的"乱码"。
怎么解决这个坑?
找到了病因,解决起来就简单了。这里给大家提供三个思路,按需取用:
1. 物理超度:直接删除或替换
如果你写这个标记只是为了自己看,或者它只是个占位符,最省事的办法就是换个不被 UnoCSS 正则盯上的写法。比如改成 citation-1,或者用 HTML 实体、Unicode 字符来代替方括号。惹不起,咱们躲得起。
2. 魔法防御:配置 blocklist
如果你非要在代码里保留这种 [citation:xxx] 的格式,可以在 UnoCSS 的配置文件里把它加到黑名单(blocklist)中,明确告诉 UnoCSS "别管这玩意儿":
typescript
// uno.config.ts
import { defineConfig } from 'unocss'
export default defineConfig({
blocklist: [
// 用正则把这种奇怪的模式屏蔽掉
/^\[citation:.+\]$/,
],
})
3. 版本迭代:升级 UnoCSS
这种明显的解析 Bug,通常在后续版本中会被修复。去 changelog 里瞅一眼,或者直接把 UnoCSS 升级到最新的稳定版(比如 0.50+)。新版本对这种非标准 class 名的容错处理已经完善了很多,不会再轻易生成非法 CSS 了。
踩坑总结
原子化 CSS 工具用起来确实爽,但它们的"贪婪扫描"机制偶尔也会误伤。
以后遇到样式突然大面积失效、页面瞬间"裸奔"的情况,别急着清缓存重启,先打开 DevTools 看看生成的 CSS 文件里,是不是混进了什么非法的"乱码"语法。往往一个不起眼的字符串,就是导致全局崩溃的元凶。