2026-04-01 10:01:02
这是困扰我很久的一个问题,每次更新 Ant Design Pro 开发的管理后台前端版本后,浏览器总是会缓存旧的文件,导致用户看到的仍然是旧版本的界面。
或者某个子功能更新,更新后,如果用户没有刷新页面,直接访问这个功能,直接白屏报错。只有当用户手动刷新页面后才能看到更新后的界面。这个体验非常的不好。
之前没怎么当回事,要么是因为后台更新频率不高,要么是后台用的人少,现在遇到了几个系统,用户量比较大,更新频率也比较高,这个问题就变得非常突出,必须要解决。
问了一下 DeepSeek, 他说这个问题的根源在于浏览器缓存了旧的 index.html 文件,虽然其他静态资源(js、css)文件名里都带了哈希(例如,app.123456.js),理论上应该是不会被缓存的,但 index.html 没有带哈希,所以浏览器会一直缓存旧的 index.html 文件,导致用户看到的界面一直是旧版本的。
HTTP/1.1 304 Not Modified
Server: nginx/1.24.0 (Ubuntu)
Date: Tue, 31 Mar 2026 09:06:17 GMT
Last-Modified: Mon, 02 Feb 2026 08:35:01 GMT
Connection: keep-alive
ETag: "698061b5-1881"
server {
listen 80;
server_name _;
client_max_body_size 8M;
# 前端静态文件根目录(提到 server 层)
root /home/some_user/some_project/frontend/dist;
index index.html index.htm;
# API 请求转发到后端 golang 服务
location /api/ {
proxy_set_header X-Forward-For $remote_addr;
proxy_set_header X-real-ip $remote_addr;
proxy_pass http://127.0.0.1:9999/api/;
}
# 所有 HTML 文件强制不缓存。存在子功能对应目录也包含 index.html 的情况,所以不能只针对根目录的 index.html 进行处理。
location ~* \.html$ {
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
add_header Expires 0;
try_files $uri =404;
}
# SPA 路由处理:其他所有请求返回 index.html
location / {
try_files $uri $uri/ /index.html =404;
}
}
检查 Nginx 配置,并 reload Nginx:
sudo nginx -t
sudo nginx -s reload
HTTP/1.1 200 OK
Server: nginx/1.24.0 (Ubuntu)
Date: Tue, 31 Mar 2026 08:33:30 GMT
Content-Type: text/html
Last-Modified: Mon, 02 Feb 2026 08:35:01 GMT
Transfer-Encoding: chunked
Connection: keep-alive
ETag: W/"698061b5-1881"
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: 0
Content-Encoding: gzip
我发现 Ant Design Pro 的前端项目目录结构中,index.html 文件是放在 dist 目录下的,同时每个子功能也有对应的子目录,里面也包含一个 index.html 文件。
而 Vue Element 则只有一个根目录的 index.html 文件,没有子功能目录下的 index.html 文件,其他都在 js 目录下。
虽然 index.html 文件的缓存问题解决了,但是我不太理解,为何修改前的返回里,也有文件的 etag 和修改时间等信息,且 etag 也不一样了,但浏览器还是会缓存旧的 index.html 文件呢?
原因是没有设置 Cache-Control: no-cache 等响应头,浏览器依然可能使用旧的缓存,而不会主动向服务器验证。
当浏览器缓存了一个资源(比如 index.html),再次请求时,是否发送验证请求取决于缓存响应的 Cache-Control 和 Expires 头。
如果响应头中带有 Cache-Control: no-cache(或 must-revalidate)。浏览器每次都会向服务器发送验证请求(带上 If-None-Match 或 If-Modified-Since),服务器根据 ETag 或 Last-Modified 决定返回 200(新内容)还是 304(未修改,使用缓存)。
如果没有 Cache-Control 或 Expires 明确指示。浏览器会使用启发式缓存(Heuristic Caching)。例如,根据 Last-Modified 时间,浏览器可能认为资源在 (当前时间 - 上次修改时间) * 10% 的时间内是新鲜的,期间根本不会发送请求,直接使用本地缓存。这就会导致即使服务器上的文件已更新(ETag 变了),浏览器也不去验证,用户看到的还是旧页面。
而用户刷新页面(F5 或 Ctrl+R):浏览器通常会忽略启发式缓存,强制发送验证请求(带上 If-None-Match),这时 ETag 不同就会返回新内容。
ETag 本身并不控制是否验证,它只用于验证时的比较。如果没有验证,ETag 再变也无用。因此,对于 index.html 这类必须实时更新的文件,必须设置 Cache-Control: no-cache(或其他强制验证的指令),让浏览器每次都必须向服务器询问,确保及时拿到最新版本。
Nginx 默认的 ETag 格式:
ETag = {文件最后修改时间的十六进制} - {文件内容长度的十六进制}
2026-03-29 22:13:40
今天吐槽了一下 Cocos Creator 3.8.8 并不支持 MCP,导致 AI 不能自动操作场景中的节点,参见前文:第一次用 AI 开发 Cocos 小游戏,我才认识到 MCP 的重要性。然后,发到小红书后,有个大佬说可以看看 Cocos 4。果然在官方论坛里找到一个关于 Cocos 4 的介绍。
https://forum.cocos.org/t/topic/172915
以前的“Cocos Creator”是一个包含引擎+编辑器的整体,而现在它被拆分成了两个独立的部分:
同时还有一个 Cocos CLI 的支持: https://github.com/cocos/cocos-cli
其实就是游戏引擎跟编辑器的剥离。
今天看到 PinK 0.0.1.12 Alpha 版本发布,这版本号看起来是远没有到正式版的地步。而且官方也不推荐用到生产环境。
对于我这种新手来说,更没有必要去踩坑了。老老实实去用 Cocos Creator 3.8.8 好了。
Cocos 4 变成了一个纯粹的游戏引擎,是在 Cocos Creator 3.8.8 的引擎基础上进行开发的。
我还是老老实实先用 Creator 3.8 开发界面吧,即便未来真的用上了 PinK,那些基础概念还是需要了解的。
2026-03-29 12:30:32
周末尝试用 Github Copilot 中的 GPT 5.4 开发我的第一款 Cocos 小游戏,我发现高达 400k 上下文的 GPT 5.4 确实强的可怕。无论是 Plan 还是代码实现,都非常专业。但是有一点遗憾,就是需要在 Cocos Creator 场景编辑器里手工创建节点层级、挂组件、绑定按钮事件。这部分 AI 没法帮你自动完成。我不是很理解,难道这些不是类似一下 XML 的配置项么?为啥不能自动完成绑定和设置。
MCP 的全称是 Model Context Protocol(模型上下文协议)。有了 MCP,AI 就可以“动手”去自动创建节点、修改属性、运行项目。
我查了一下,有一款三方实现的 Cocos MCP 三方插件:
https://github.com/DaxianLee/cocos-mcp-server
一个适用于 Cocos Creator 3.8+ 的综合性 MCP(模型上下文协议)服务器插件,使 AI 助手能够通过标准化协议与 Cocos Creator 编辑器进行交互。一键安装和使用,省去所有繁琐环境和配置。已经测试过Claude客户端Claude CLI和Cursor,其他的编辑器理论上也完美支持。🚀 现在提供 50 个强力融合工具,实现99%的编辑器控制!
Cocos dashboard 中有对应的付费版本,如下图:

这是我最不能理解的地方,这样重要的功能居然不是官方支持的,而是由一个三方插件实现的。我甚至开始怀疑 Cocos 要跑路了,对我自己的选型有点动摇了。我这周尝试了一下 Google Stitch,就是用 AI 出设计稿,简直强的可怕。
这也是我第一次感受到 MCP 的重要性,如果所有的开发工具都支持 MCP,那确实可以大大提升效率。之前主要是担心数据安全性问题,没有尝试 MySQL MCP 和 Chrome MCP。现在来看有点过于谨慎了,如果做好备份和账号隔离,还是可以规避风险的。
2026-03-27 14:47:59
今天同事反馈人事系统导出花名册 Excel 时,员工的全日制第一学历信息提取错误。
搞得我一头雾水。。。😓 当初就不应该接这个人事系统的项目,坑又多,又没有成就感。
现在还原一下这个问题的来龙去脉。
例如,这个员工的教育经历如下:
而我在导出时,把全日制第一学历提取成了高中学历。人事说这个人的全日制第一学历应该是研究生,同时,这个人的最高学历也是研究生。
我表示很疑惑,我以为这个人的全日制第一学历应该是大学本科。。。
我问了以下 DeepSeek, AI 也说我的理解没啥问题(印象中我在 VSCode 中让 AI 做 Code Review 也没有发现问题)。但是在知乎上看一些职业 HR 说全日制第一学历其实指的是全日制的最高学历。
也就是说,这个人的全日制第一学历应该是研究生,而不是大学本科。
还有另外一种情况,例如另外一个人的教育经历如下:
那么这种情况,这个人的全日制第一学历应该是大学本科,而不是研究生。因为这个人的研究生学历是非全日制的。
但是,其最高学历是研究生,虽然不是全日制。
当然,这三个,我完全看不出有什么区别。。。
2026-03-26 20:54:24
最近增加了博客新功能,中文版自动翻译为英文,基于 Github Copilot SDK 的免费 gpt 5 mini 模型。但是,今天看了 Bing Web Master 里的一篇文章,说这种翻译行为,也会被认定为重复内容。参考下文:
https://blogs.bing.com/webmaster/December-2025/Does-Duplicate-Content-Hurt-SEO-and-AI-Search-Visibility
Localization creates duplicate content when regional or language pages are nearly identical and do not provide meaningful differences for users in each market.
那么如果一个网站内,同一篇文章,同时存在中文版本和英文版本,如何设置页面信息,防止被搜索引擎认定为重复内容?
判断如果为中文 , 且已翻译为英文:
在中文版页面的头部添加:
<link rel="alternate" hreflang="zh-CN" href="https://www.sunzhongwei.com/xxx" />
<link rel="alternate" hreflang="en" href="https://www.sunzhongwei.com/xxx-en" />
<link rel="alternate" hreflang="x-default" href="https://www.sunzhongwei.com/xxx-en" />
判断如果文章内容为英文,在英文版页面的头部添加:
<link rel="alternate" hreflang="zh-CN" href="https://www.sunzhongwei.com/xxx" />
<link rel="alternate" hreflang="en" href="https://www.sunzhongwei.com/xxx-en" />
<link rel="alternate" hreflang="x-default" href="https://www.sunzhongwei.com/xxx-en" />
用于向搜索引擎(尤其是 Google、Bing 等)说明:当前网页存在其他语言或地区的替代版本。帮助搜索引擎理解多语言/多地区网站的结构,从而在搜索结果中根据用户的语言偏好或地理位置,自动展示最合适的页面版本,同时避免因内容相似而导致的“重复内容”问题。
晚上吃完饭,在博客上增加了这个逻辑处理。但是,感觉页面增加的逻辑越来越多了,以后会不会不好维护 😓
2026-03-26 10:12:12
早上没起床就收到一封 Github 的邮件提醒,大意是:
我们正在更新 GitHub 使用数据以改进 AI 辅助编码工具的方式。自 4 月 24 日起,您与 GitHub Copilot 的交互(包括输入、输出、代码片段及相关上下文)可能会用于训练和优化 AI 模型,除非您选择退出。
我 X,这是要对齐一众国内流氓产品了吗?好在是给了禁用的设置,于是今天上班的第一件事就是赶紧禁用这个训练选项。
浏览器登录 github 网页版,一进去就能看到顶部的醒目提醒:
On April 24 we’ll start using GitHub Copilot interaction data for AI model training unless you opt out. Review this update and manage your preferences in your GitHub account settings.
点击 GitHub account settings 那个链接即可进入。或者手动输入地址:
https://github.com/settings/copilot/features
在页面底部,找到 Privacy - Allow GitHub to use my data for AI model training,选择 Disabled,即可完成禁用。

不过,我发现我的设置默认就是禁用状态,估计是我第一次开通 github copilot pro 会员时,就已经设置过了。还是我的安全意识比较强啊。
我觉得这次 github 的做法很不厚道,如果是免费的会员我倒是可以理解,但是连付费的会员也默认来这一手,我觉得就完全说不过去了。毕竟大部分人都是打工人,写的代码都是企业的财产,拿去做 AI 模型训练完全没有道理。这个世界疯了 😓