[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"site":3,"post-re-li-tu-cong-github-zhua-shu-ju":59,"related-re-li-tu-cong-github-zhua-shu-ju":78},{"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":72,"next":75},"re-li-tu-cong-github-zhua-shu-ju","热力图从 GitHub 抓数据，私有仓库不算","匿名抓取只有公开贡献。换成 GraphQL 加令牌之后数字才对得上，代价是要管一个会过期的令牌。","2026-05-06","2026-10-17",[66],"Node","首页放了个提交热力图，数据从 GitHub 拉。做法是抓它个人主页上那个公开的事件接口，解析出每天的提交数。\n\n上线后我自己看了一眼 GitHub，发现数字对不上：主页上明明更密。\n\n原因是匿名抓取只能拿到公开贡献。我有几个练习放在私有仓库里，接口根本不返回。GitHub 上自己登录着能看到，是因为登录状态下的页面走的是 GraphQL，带鉴权。\n\n要一致只能也走 GraphQL：\n\n```ts\nconst query = `{\n  user(login: \"hsgjq\") {\n    contributionsCollection { contributionCalendar { weeks { days { contributionCount date } } } }\n  }\n}`\n```\n\n配一个令牌，放在服务端环境变量里。这样首页显示的就和我自己看到的一致了。\n\n代价有三条，我衡量过才做：\n\n令牌会过期。classic 令牌最长一年，到期那天接口 401，热力图变空白。所以我加了降级：抓不到就显示\"暂时无法获取\"，而不是让整页报错。这条比错误处理本身重要——首页不能因为一个装饰模块挂掉。\n\n多了一次外部依赖。GitHub 挂了、限流了、接口改了，都会影响我的首页。所以这个请求设了超时（3 秒），并且结果缓存一小时，不做实时。\n\n隐私。用带权限的令牌去查公开数据，我给它的最小权限是只读 public 信息，不给 repo 权限。\n\n限流那条要单独记：匿名请求每小时 60 次，带令牌 5000 次。我一开始没缓存，页面每次刷新都打一次，测试时一小时就把配额用完了。","Node 写接口",11,[71],{"slug":60,"title":61,"seriesIndex":69},{"slug":73,"title":74},"rss-he-sitemap-shi-zen-me-bei-pa","RSS 和 sitemap 是怎么被爬虫看到的",{"slug":76,"title":77},"tou-xiang-cong-base64-gai-cheng-wen-jian","头像从 base64 改成文件存储",[79,84,94,100,105],{"slug":76,"title":77,"excerpt":80,"date":81,"tags":82},"base64 塞进数据库之后每次查询都拖一大坨。改成存路径、文件进卷，还要处理历史数据怎么迁移。","2026-05-19",[83,66],"MySQL",{"slug":85,"title":86,"excerpt":87,"date":88,"tags":89},"gang-deng-lu-jiu-guo-qi-yi-ci","一个 401，查出四个前端机制：缓存回放、隐藏页的 rAF、百分比圆角、缓动过冲","响应头里的 token 被 304 原样回放，把刚签发的新 token 顶掉，表现成刚登录就过期。顺带记三个前端细节：隐藏标签页里 rAF 不执行、扁盒子的 50% 圆角是胶囊、缓动曲线的过冲只有 0.0008。","2026-10-13",[90,91,92,93],"CSS","JavaScript","Vue","浏览器",{"slug":95,"title":96,"excerpt":97,"date":98,"tags":99},"dian-xiang-mu-ye-mian-jiu-si-yi","点「项目」页面就死：一次客户端无限重定向","为了保留旧地址大小写加的一条跳转规则，被注册成了客户端路由；路由匹配不区分大小写，于是它自己跳自己。","2026-10-02",[12,93],{"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],"随笔"]