背景 链接到标题

原有站点基于传统 CMS,内容管理成本高,改动一次需要走完整的发布流程。业务方希望站点更轻、更稳、更容易维护,最终决定重构为纯静态站点。

技术选型 链接到标题

最终选用 Astro 7 + Tailwind 3,output: "static",输出纯静态文件,零客户端 JS,部署到对象存储 + CDN。

选择理由:

  • Astro 的 Islands 架构默认不输出 JS,适合以内容为主的官网
  • Tailwind 3 的 JIT 模式可以快速迭代 UI,无需手写大量 CSS
  • 静态产物可直接托管到任何对象存储,成本低、访问快

目录结构与路由 链接到标题

src/
  pages/
    index.astro          # 首页
    about.astro          # 关于
    contact.astro        # 联系
    services/
      index.astro        # 服务列表
      [slug].astro       # 服务详情(动态路由)
    404.astro            # 自定义 404
  layouts/
    BaseLayout.astro     # 全局布局
  components/
    SiteNav.astro        # 导航
    Hero.astro           # 首屏
    ServiceCard.astro    # 服务卡片
    SiteFooter.astro     # 页脚
  data/
    services.ts          # 服务数据
  styles/
    global.css           # 全局样式 + 自定义工具类

关键设计:服务数据集中存放在 services.ts[slug].astro 通过 getStaticPaths 自动生成静态页面,新增服务只需改数据文件,无需新增路由。

核心设计决策 链接到标题

设计系统:浅色简约风,单一品牌渐变(violet → cyan),配合大留白、细描边、微投影,整体参考 Linear / Stripe 官网的克制精致感。

字体:Inter(英文/数字)+ 系统中文栈,通过 Google Fonts 引入。

自定义工具类:定义在 global.css 中,通过 BaseLayout.astro 全局引入:

  • .text-gradient:紫青渐变文字
  • .bg-grid:淡色网格背景
  • .card-hover:hover 上浮 + 紫色辉光投影

服务数据驱动 链接到标题

services.ts 定义服务数组,每项包含 slugtitleicondescriptionfullDescriptionhighlights 六个字段。

服务列表页和详情页都从这个数据源渲染。新增服务时只需在 services.ts 添加条目,并在 public/icons/ 下添加对应 SVG 图标,路由自动生成。

部署流程 链接到标题

构建产物在 dist/,一键部署脚本完成三个步骤:

  1. npm run build 生成静态文件
  2. 同步到对象存储,根 index.html 单独设置不缓存头,其余资源长期缓存
  3. 触发 CDN 目录刷新,让最新版本生效

站点完全静态,没有数据库,没有运行时依赖,回滚只需重新上传产物。

踩坑记录 链接到标题

子目录首页未开启导致页面丢失

对象存储默认不处理目录索引。访问 /services 时返回 NoSuchKey XML,需要手动开启「子目录首页」并填入 index.html

oss sync 的 exclude 陷阱

--exclude "index.html" 按文件名匹配,会排除所有子目录下的 index.html,导致 /services/about 等页面全部丢失。改用全量同步 + 单独处理根 index.html 的缓存头。

二进制文件被静默跳过

对象存储的同步工具对二进制文件若大小恰好与原文件相同会跳过,修改 logo 或 favicon 后需要加 --force 强制覆盖。

404 页需要单独配置

404.html 上传后,还需在对象存储控制台的「静态网站托管」中手动填入默认 404 页,否则不会自动调用。

总结 链接到标题

Astro 适合以内容为主的官网:零客户端 JS、组件化开发体验、纯静态产物。配合 Tailwind 的 utility-first 方式,UI 迭代速度快,维护成本低。部署到对象存储 + CDN 的方案简单可靠,适合不需要后端的展示型站点。