注册了 qexlab.com,把这个实验室品牌站从空目录做到了 HTTPS 上线。这篇笔记记录关键决策和踩过的坑,供以后参考。
为什么是 Astro
候选有四个:纯静态 HTML、Astro、Next.js、Hugo。最终选 Astro 的理由:
- 零 JS 默认输出——主页和工具页大多是静态内容,Astro 不往浏览器塞运行库
- 内容集合(Content Collections)——博客模块的 Markdown 管理开箱即用,带类型检查的 frontmatter
- 内置 i18n 路由——
/zh/en前缀分离,不用自己造轮子 - Islands 架构——以后做可视化实验时,可以只在需要的角落嵌入交互组件
纯 HTML 的问题是后面加博客要重构;Next.js 对一个内容站来说太重;Hugo 很快但模板系统不如组件灵活。
ICP 备案:境内站的硬性前置
服务器在腾讯云上海机房,境内服务器提供 Web 服务必须完成 ICP 备案,否则 80/443 端口会被阻断。两个容易忽略的点:
- 备案号必须展示在页脚并链接到
beian.miit.gov.cn,腾讯云会巡检,缺了会被警告甚至阻断 - 备案通过前不要急着把域名解析到境内 IP
页脚实现成条件渲染:备案号为空不显示,填入配置后自动出现。
部署:静态站的极简路径
npm run build # 产物在 dist/
scp -r dist/. root@<IP>:/var/www/qexlab/ # 上传
Nginx 配置里值得写的就两条:/_astro/ 目录下的资源带内容哈希,可以放心给 30 天缓存;try_files $uri $uri/ =404 适配 Astro 的目录式路由。HTTPS 用 certbot 一行解决,自动续期。
踩坑记录
浮点舍入会算错涨跌停价。 10.05 × 1.1 在 IEEE754 下是 11.054999…,直接 Math.round(x*100) 会得到 11.05 而非正确的 11.06。解法:价格先转整数(分),全程整数运算,最后除回来。涉及钱的计算不要用浮点。
Astro frontmatter 不接受多行前导 | 联合类型。 这种写法会让构建报 Unexpected "|":
// 会炸
export type ToolId =
| 'limit-price'
| 'calendar';
// 没问题
export type ToolId = 'limit-price' | 'calendar';
define:vars 的脚本是内联的。 一旦用了 define:vars 传数据,这个 <script> 就不能再 import——数据要序列化传进去,逻辑要么内联要么拆到不带 define:vars 的脚本里。
语言切换不该回主页。 第一版导航的语言切换写死跳对方主页,在工具页点「EN」会莫名回首页。修正为只替换 URL 里的语言前缀;文章页如果没有对应翻译,则回退到对方的博客列表,避免 404。
接下来
博客刚开张,实验日志(Exp.001 起)在路上。工具集已有六个,会继续扩充。如果你觉得哪里做得不对,欢迎到 GitHub 提 issue(仓库公开后会在主页挂上)。