Vue 3偶发字体乱码 - 原因探究

背景:

最近因为项目构建速度过慢,调试速度过慢,把100万行的Vue2项目升级到Vue3 + Vite了,顺手把Element UI升到Plus, Vxe什么都升级了。结果所有其他bug都修完后,测试报来一个神奇的问题, 而且居然是偶发的

预期:

实际结果

分析过程

到测试电脑上点进对应style看看:

js 复制代码
.vxe-table-icon-checkbox-unchecked:before {
    content: "";// 乱码
}

刷新后再打开同个站点却是:

js 复制代码
.vxe-table-icon-checkbox-unchecked::before {
    content: ""; // 正常了
}

回到自己的工位上面, 尝试通过页面GET访问这个css文件,第一次:

js 复制代码
.vxe-table-icon-checkbox-unchecked:before{
    content:"顪�" // 中文乱码,GB2312无疑
}

刷新后:

js 复制代码
.vxe-table-icon-checkbox-unchecked:before {
    content: "";// 乱码
}

再刷新几次就在这两个编码格式之间随机出现。

难道css文件还能不一样的?确认了一下,对应css文件的hash完全一致。都是app.84091779.css,并且如果是不同文件,怎么可能是偶发bug。

从docker里面把对应css文件下载下来,本地CURSOR试着改了改编码测了一下,发现测试的主机上偶发的编码格式是windows1252,刷新后的编码是utf-8。

看了一下对应的CSS文件的Response头

js 复制代码
content-type: text/css

并没有指定charset, 看起来确定是编码问题了。但是这里为什么是偶发的, 基于以前的经验以及AI的回答简单分析下

偶发原因

前提条件

  • 无 Content-Type: charset=
  • 无 @charset 规则
  • 无 BOM
  • 无 HTML 引用文档(直接访问 CSS)

此时浏览器走编码嗅探算法(Encoding Sniffer),而TCP 分包导致嗅探窗口不同,这才是问题的根源 编码嗅探器不会等整个文件下载完,它只扫描首次可用的字节块来做判断。

请求1: 首个 TCP 包包含字节 A~B → 嗅探器认为是 GB2312

请求2: 首个 TCP 包包含字节 A~C(多了一点)→ 嗅探器认为是 Windows-1252

每次请求的 TCP 分包边界不固定(受网络抖动、服务器 buffer 状态影响),导致嗅探器"看到的初始窗口"不同,输出结果不同。


GB2312 和 Windows-1252 为什么特别容易互相误判

这两个编码的字节范围有严重重叠:

字节范围 GB2312 Windows-1252
0x80--0x9F 无效/不用 可打印字符(€ 等)
0xA1--0xFE 汉字双字节 高位拉丁字符

当 CSS 文件包含中文注释或中文内容(哪怕是 UTF-8 编码的,某些字节恰好落在这个范围),嗅探算法的统计模型看到不同长度的样本,可能得出不同结论。

最终方案

nginx css文件头配置里面添加charset=utf-8。

外记

毕竟是AI做的最终分析,还是需要真正去确认是否是浏览器嗅探机制。可以使用wireshark抓一下包

  1. 过滤 tcp && ip.addr == 你的服务器IP
  1. 对比两次请求,看首个数据包(PSH 标志)携带了多少字节
  1. 如果第一帧字节数不同,就能解释为什么嗅探结果不一致
相关推荐
BD_Marathon4 分钟前
部署Spark
大数据·javascript·spark
敲代码的玉米C15 分钟前
我修的那个 bug,制造了另一个 bug
前端·人工智能·架构
gis开发之家24 分钟前
《Vue3 从入门到大神50篇》Vue3 源码详解(二十):生命周期钩子源码解析 —— onMounted / onUpdated 如何实现?
前端·javascript·前端框架·vue3·vue3源码
全栈项目管理程序猿27 分钟前
ArcGIS JS 基础教程(9):天空盒与大气效果
javascript
Narrastory27 分钟前
我用 Claude Code 写代码不到 2 小时,却花了 3 天做完这个软件—Vibe Coding 的正确姿势,是设计不是生成
前端·人工智能·github
Enaium29 分钟前
我实现了KMP的SDL绑定并编写了高性能软光追
前端·kotlin
古夕33 分钟前
本地正常线上白屏:一次路由切换后刷新恢复问题的排查与修复
前端·ai编程
栀鸢ouo40 分钟前
解决Element Plus表格展开行横向溢出、滚动截断问题(项目实战方案)
前端·vue.js
用户390513321928844 分钟前
写了5年JS,才发现这10个方法能少写一半代码
前端
平凡的阿泽44 分钟前
我用TRAE Work手搓了一个「谁是卧底」小游戏
前端·javascript