最近在 GitHub 上偶然发现一个非常不错的开源静态工具站项目。整个网站在编译后,可以直接部署到 Cloudflare Pages 上,无需任何后端服务支持——这一点真的非常方便。
不过在阅读源码时,我注意到两个比较明显的问题:
项目虽然区分了 index、about、contact us 等页面,但主要功能还是依然集中在 index 中,并且页面的内容是通过 JavaScript 在浏览器端动态生成的,这种方式对 SEO(搜索引擎优化)极其不友好。
作者在最初的设计中并没有考虑多语言支持。页面中的文本有的直接写在 HTML 里,有的放在 JSON 配置文件中,还有一部分编写在 JS 代码中,由 JS 动态生成,这让多语言翻译变得相当麻烦。
为了解决这些问题,我希望实现以下目标:
保留并复用项目中已有的 JS 功能代码。
将所有页面输出的文本内容尽量统一到 JSON 配置文件中管理。
每个独立功能都对应独立的页面,能静态化的都尽量静态话,不再依赖前端 JS 动态生成页面元素。
不同语言的页面分目录输出,比如英文版放在 en 目录下,中文版放在 zh 目录下,以便更好地维护。
基于这些需求,我决定使用 Astro 来实现页面的静态化。原本以为整个任务会很快完成,毕竟现在有AI的夹持,许多开发任务,尤其是项目重构都变的非常简单了。但是在实现过程中,却正是因为AI的参与,导致我花费了整个下午,才解决掉这个问题。
在原有的项目中,Icon库使用的是 Lucide ,本着尽量沿用原始代码的原则,使用Astro重构时,我也继续使用Lucide。
Lucide 的官方文档中有专门针对 Astro 调用图标组件的方式:Lucide Astro 指南 。
当需要动态调用 Lucide Icon 时,文档中提供了如下代码示例:
创建Icon组件 LucideIcon.astro
---
import { icons, type IconProps } from '@lucide/astro';
interface Props extends IconProps {
name: keyof typeof icons;
}
const { name, ...restProps } = Astro.props;
const Icon = icons[name];
---
<Icon {...restProps} />
调用Icon组件 Page.astro
---
import LucideIcon from './LucideIcon.astro';
---
<LucideIcon name="RulerDimensionLine" />
重要 从文档的说明可以看出,调用Icon组件时,传入的name需要是单词首字母大写的驼峰格式。
但是实际编码时,最初我尝试几种AI,如Google Gemini 2.5 pro, GPT-5等,却都一直固执的认为icons[name]中,name值需要是全小写,使用“-”连接的格式。
每当在VsCode中使用AI修改代码时,Icon组件代码就被修改为:
---
import { icons, type IconProps } from '@lucide/astro';
interface Props extends IconProps {
name: keyof typeof icons;
}
const { name : camelCaseName, ...restProps } = Astro.props;
const kebabCaseName = camelCaseName.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
const Icon = icons[kebabCaseName as keyof typeof icons];
---
<Icon {...restProps} />
警告 原本正常调用Icon组件的name=“RulerDimensionLine”,AI修改后等于变成name=“ruler-dimension-line”。
AI坚持这样的认知,不知道是因为训练时错误代码被代入,还是在当时,Lucide的某个版本中icons[name]使用的name就是全小写格式的。