[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"site":3,"post-shen-se-mo-shi-yan-se-bian-liang":59,"related-shen-se-mo-shi-yan-se-bian-liang":80},{"name":4,"url":5,"description":6,"bio":7,"avatar":8,"skills":9,"tools":16,"social":34,"hero":47,"heatmap":52,"icp":55,"police":56,"policeIcon":57,"shortName":58},"时过境迁技术笔记","https:\u002F\u002Fhsgjq.top","一个记录前端与 Node 实践的个人博客，内容围绕 Vue、Nuxt、NestJS 与工程化展开，附源码级的原理笔记。","一名热爱技术的全栈开发者，专注 TypeScript 与 Web 工程化，习惯把踩过的坑和思考记录在这里。","\u002Fuploads\u002Fc485c101-179e-48db-96d1-238693784c38.jpg",[10,11,12,13,14,15],"TypeScript","Vue 3","Nuxt","NestJS","Node.js","工程化",[17,23,28],{"items":18,"title":22},[19,20,21],"Cursor","Git","Chrome DevTools","开发工具",{"items":24,"title":27},[25,26],"Vite","npm","构建工具",{"items":29,"title":33},[30,31,32],"Docker","CI\u002FCD(GitHub Actions)","Vercel","部署运维",[35,39,43],{"href":36,"icon":37,"label":38},"https:\u002F\u002Fgithub.com\u002Fhsgjq","github","GitHub",{"href":40,"icon":41,"label":42},"2971861643@qq.com","mail","邮箱",{"href":44,"icon":45,"label":46},"\u002Frss.xml","rss","RSS",{"lines":48,"subtitle":51},[49,50],"人生若只如初见，","何事秋风悲画扇。","《木兰花·拟古决绝词柬友》",{"enabled":53,"platform":37,"username":54},true,"hsgjq","桂ICP备2024046985号","桂公网安备45011002000103号","\u002Fuploads\u002F72c67ef3-bc86-4b64-b0df-0aba71065050.png","时过境迁",{"slug":60,"title":61,"excerpt":62,"date":63,"updatedAt":64,"tags":65,"content":67,"series":68,"seriesIndex":69,"seriesNav":70,"prev":76,"next":77},"shen-se-mo-shi-yan-se-bian-liang","深色模式：颜色变量该放哪一层","语义变量而不是具体色值，切换只改一组自定义属性。闪烁问题出在样式加载时机，不是 JS。","2026-06-16","2026-10-15",[66],"CSS","第一版实现：每个组件里写 @media (prefers-color-scheme: dark) { ... }。加了二十个组件之后我改不动了——想微调一个背景色要在二十个文件里各改一次。\n\n问题在于颜色被写到了使用处。正确的分层是三层：\n\n最底层是原始色板，只有色值，没有语义，也不该被组件直接引用：\n\n```css\n:root { --gray-900: #16181d; --gray-100: #f2f3f5 }\n```\n\n中间层是语义变量，回答\"这个颜色用来干什么\"：\n\n```css\n:root { --bg: #fff; --fg: #1f2328; --muted: #6b7280; --border: #e5e7eb }\n[data-theme='dark'] { --bg: #16181d; --fg: #e6e8eb; --muted: #8b929c; --border: #2a2e37 }\n```\n\n最上层是组件，只用语义变量：background: var(--bg); color: var(--fg)。\n\n切换主题时只换中间层的一组值，组件一行不动。\n\n第二件事是首屏闪烁。用 JS 在挂载后设置 data-theme，会先按浅色渲染一帧再跳成深色，肉眼很明显。原因是脚本在 body 末尾。把读取偏好并设置属性的那段内联到 \u003Chead> 里、放在样式之前，闪烁就没了。\n\n第三件事是别只反转颜色。深色下纯黑背景配纯白文字对比过高，看久了刺眼；阴影几乎不可见，分隔只能靠边框和亮度差；图片和头像在深色背景上会显得发亮，我给它加了 opacity: .9。这些不是配色技巧，是\"深色不是浅色的反相\"这件事的具体含义。\n\n最后，跟随系统只是默认值，要给用户一个手动开关并把选择存下来，否则在系统设了深色而用户想要浅色的时候，他只能改系统设置。","从零切图",12,[71,75],{"slug":72,"title":73,"seriesIndex":74},"fen-ye-zu-jian-zai-shou-ji-shang","分页组件在手机上顶掉一行",11,{"slug":60,"title":61,"seriesIndex":69},{"slug":72,"title":73},{"slug":78,"title":79},"zhong-wen-zi-ti-zi-ji-hua-zhi","中文字体子集化之后首屏少了 900KB",[81,90,94,100,105],{"slug":82,"title":83,"excerpt":84,"date":85,"tags":86},"gang-deng-lu-jiu-guo-qi-yi-ci","一个 401，查出四个前端机制：缓存回放、隐藏页的 rAF、百分比圆角、缓动过冲","响应头里的 token 被 304 原样回放，把刚签发的新 token 顶掉，表现成刚登录就过期。顺带记三个前端细节：隐藏标签页里 rAF 不执行、扁盒子的 50% 圆角是胶囊、缓动曲线的过冲只有 0.0008。","2026-10-13",[66,87,88,89],"JavaScript","Vue","浏览器",{"slug":72,"title":73,"excerpt":91,"date":92,"tags":93},"flex 里有个\"不允许压缩\"的兄弟项，就会把列表挤出去。min-width: 0 这个开关单独说一次。","2026-06-02",[66],{"slug":95,"title":96,"excerpt":97,"date":98,"tags":99},"dian-xiang-mu-ye-mian-jiu-si-yi","点「项目」页面就死：一次客户端无限重定向","为了保留旧地址大小写加的一条跳转规则，被注册成了客户端路由；路由匹配不区分大小写，于是它自己跳自己。","2026-10-02",[12,89],{"slug":101,"title":102,"excerpt":103,"date":98,"tags":104},"cong-da-bao-shang-chuan-dao-push-ji","从打包上传到 push 即上线：把 CD 接通","私有仓库的镜像包默认也是私有的，健康检查的探测地址在宿主机有 nginx 时会打错地方。两处都是配好之后才验出来的。",[30,15],{"slug":106,"title":107,"excerpt":108,"date":109,"tags":110},"shang-xian-na-tian-yu-ming-zheng-shu","上线那天：域名、证书，和一条我打错的 IP","把 69 打成 96，于是照着\"安全组没放行\"这条错线索查了一整晚。分层排查的前提是先确认敲的是哪扇门。","2026-10-01",[111],"随笔"]