把 Cursor 当工程工具,而不是聊天窗口 很多人刚开始用 Cursor 时,会把它当成一个更懂代码的聊天窗口。遇到问题就把需求、日志、截图、文件一股脑放进去,然后开 Agent 等它改。 短期看,这样确实省事。长期看,很容易遇到几个问题:模型越用越贵,上下文越来越乱,Agent 改动越来越大,最后 review 成本反而升上去。AI Coding 的价值来自一组匹配关系:合适的任务、合适的上下文、合适的模型,以及合适的验证方式。 有位技术 2026-06-01
Vite library mode 里漏到 Chrome Extension 的 process.env Chrome Extension 里遇到过一个很隐蔽的问题:content script 一加载就报 process is not defined,但同一个扩展里的 popup 一直正常。 麻烦点在于,两边都用了同一个依赖。只看依赖名,很容易以为「既然 popup 没报错,content script 也不应该报错」。真正的差异不在依赖,而在 Vite 的构建形态:popup 是普通 HTML a 2026-06-01
一次 Git 历史压平惊魂:orphan 分支和 git add -A 的坑 这次没有造成真实损失,但过程足够吓人。 一个本地小工具仓库准备改名,并考虑放到公网私有仓库里。发布前需要先做一件事:清掉历史里和旧项目、旧公司环境相关的痕迹。当前文件已经基本改干净,但 Git 历史里仍然保留旧提交,所以最后还要把仓库压成一个新的初始化提交。 目标本来很明确: 当前源码保持完整。 当前内容里不要再出现旧项目名、旧域名、旧包名。 Git 历史只留下一个 初始化项目 commit。 2026-05-30
后台管理系统常见 UX 问题总结 最近做了一次后台管理系统的 UX 评审。 原始材料是一份很长的问题清单,里面有 30 类问题。它当然可以写成「问题大全」和「整改事项」,但如果要写给更多做后台系统的人看,我更想换一个角度:开发后台管理系统时,有哪些体验细节应该在一开始就想清楚,而不是上线后再靠评审逐页补。 后台系统更像一个长期工作台,和展示页、营销站的阅读方式不同。用户每天打开它,是为了查数据、扫列表、筛选记录、批量处理、导出结果 2026-05-29
一次 Astro 静态构建里被误导的 MissingSharp 排查记录 记录一次构建排查现场。 CI 报的是 MissingSharp,但硬盘上并不缺 sharp。页面里一行看似无害的 server import,在 Astro 静态构建阶段启动了一整条服务端副作用链,最后把错误带到了图片优化阶段的 native / CJS 包加载上。 现场现象项目是一个 monorepo 里的 Astro 站点: apps/japanese-official-websit 2026-05-28
Chrome Extension debugger 与 CDP 的能力边界 Chrome Extension 里有一个看起来很少用、但能力很强的权限:debugger。 它的作用可以理解为:让扩展通过 Chrome DevTools Protocol(CDP)连接到浏览器调试后端。扩展一旦拿到这个权限,就能对目标标签页发送一部分 DevTools 协议命令。 这类能力平时不应该随手用。它会触发明显的权限警告,调用时浏览器还会出现「某某扩展 started debuggin 2026-05-26
Vue script setup 中组件静默消失的原因:一次命名冲突排查 Vue 3 的 <script setup> 很好用,但它也会把一些原本显式的东西变成编译器规则。平时这让代码更短,出问题时也会让排查路径变得很绕。 这次记录的是一个真实排查:页面里一个组件没有渲染出来,控制台没有明显 error,最后发现原因是 <script setup> 里的普通变量名和组件名只差大小写,模板编译时把组件 tag 解析到了错误的变量上。 问题本身不复杂 2026-05-26
Vue script setup 中 defineProps 的编译边界与错误排查 在 Vue 3 的 <script setup> 里,defineProps 看起来像一个函数,但它不是普通运行时函数。它是 编译器宏:源码里写出来,构建时被 @vue/compiler-sfc 识别并替换,最终运行在浏览器里的代码里不应该再出现它。 这个差别平时不太容易被注意到,因为常见写法都很自然: const props = defineProps<{ foo: 2026-05-23
把微信收藏表情导出来,再分批导入飞书 微信里收藏了很多表情包,换到飞书以后,真正麻烦的是「怎么批量搬过去」。 微信客户端没有给「收藏的单个表情」提供正式的批量导出入口。飞书也不能直接导入几百张图片,它一次只能导入 50 张图。 最后采用的方案很直接: 先让微信网页版看到这些表情,再从网页里把图片资源取出来,最后按 50 个一组打成 zip。微信负责把表情发出来,浏览器负责拿资源,脚本负责收集和分组。 操作步骤实际操作分两段。 第一段, 2026-04-24
自己写小工具时,技术选型应该先想清楚什么 很多内部小工具一开始都不是「项目」。 它可能只是一个发布脚本、一次数据修复、一个本地调试入口、一个把表格内容写进浏览器缓存的 Chrome Extension,也可能只是一个今天临时要跑的迁移脚本。 这种东西最容易被低估。代码不多,看起来随手写几行就能跑;但它一旦接上真实副作用,比如上传 OSS、写线上缓存、改数据库、调用接口、批量处理文件,技术选型就不再只是「怎么快点写完」。 小工具的技术选型要 2026-04-10