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. 如果第一帧字节数不同,就能解释为什么嗅探结果不一致
相关推荐
刘发财1 小时前
前端2秒生成500页矢量PDF,rust真的强到没朋友
前端·javascript·rust
郑州光合科技余经理2 小时前
国际版外卖系统:税率字段怎么和订单主流程解耦
android·java·开发语言·前端·后端·php·ai编程
梦想平凡2 小时前
百游棋牌源代码开发搭建教程(十):隔离部署、备份恢复与双端验收
java·前端·javascript·数据库·源代码管理
yume_sibai4 小时前
06-Rust Web 开发实战(Axum 框架 + 数据库 + JWT 认证 + 中间件 + 部署)
前端·数据库·rust
计算机魔术师5 小时前
特朗普上台打给黄仁勋:AI末日论是骗局,我们绝不让它发生
前端
troy1285 小时前
Python 基础语法(八):Web 后端开发、数据分析与可视化、网络爬虫、人工智能 / 大模型应用
前端·python·数据分析
计算机魔术师5 小时前
CEO说要慢下来,黑客说别做梦了——同一篇论文,两种命运
前端
kyriewen6 小时前
我花3天抓了一个幽灵bug,凶手藏在第4层
前端·javascript·程序员
IT_陈寒7 小时前
Java里用Stream.parallel()翻车实录,这性能还不如单线程
前端·人工智能·后端
Bs_MoneyMagnet7 小时前
基于springboot+vue的生态果园采摘预约系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·毕业设计·计算机毕业设计