F FisherHub Docs

03. 样式与部署

Tailwind CSS v4 集成

Tailwind CSS v4 完全重写了底层引擎,采用 CSS-first 配置方式。不再需要 tailwind.config.js@tailwind base/components/utilities 指令,而是用原生 CSS 语法定义一切。

在 Astro 项目中集成 Tailwind CSS v4 只需要安装两个包:

bun add tailwindcss @tailwindcss/vite

astro.config.mjs 中配置 Vite 插件:

// astro.config.mjs
import { defineConfig } from 'astro/config'
import tailwindcss from '@tailwindcss/vite'

export default defineConfig({
  site: 'https://example.com',
  vite: {
    plugins: [tailwindcss()],
  },
})

在全局 CSS 文件中导入 Tailwind:

/* src/styles/global.css */
@import 'tailwindcss';

这个 @import 会引入 Tailwind 的所有工具类(utilities),包括 flexgridp-4text-lg 等。

@theme 设计令牌

Tailwind CSS v4 使用 CSS 原生的 @theme 指令定义设计令牌(design tokens),替代旧的 theme.extend 配置:

/* src/styles/global.css */
@import 'tailwindcss';

@theme {
  /* 品牌色 */
  --color-brand: #eb5600;
  --color-brand-light: #ff7a2e;

  /* 中性色 */
  --color-surface: #ffffff;
  --color-surface-secondary: #f5f5f5;
  --color-border: #e5e5e5;

  /* 文字色 */
  --color-text-primary: #1a1a1a;
  --color-text-secondary: #6b7280;
  --color-text-muted: #9ca3af;

  /* 间距 */
  --spacing-page: 1.5rem;
  --spacing-section: 3rem;

  /* 圆角 */
  --radius-sm: 0.375rem;
  --radius-md: 0.5rem;
  --radius-lg: 0.75rem;
}

定义之后,这些令牌可以直接在 HTML 中使用:

<nav style="background: var(--color-surface); border-bottom: 1px solid var(--color-border);">
  <a href="/" style="color: var(--color-brand); font-weight: 600;">
    Logo
  </a>
</nav>

也可以在 Tailwind 工具类中使用:

<button class="bg-brand text-white px-4 py-2 rounded-md hover:bg-brand-light">
  点击
</button>

暗色模式

Tailwind CSS v4 支持通过 @variant 自定义暗色模式变体。结合 CSS 变量,可以实现平滑的主题切换。

global.css 中定义暗色变量:

/* src/styles/global.css */
@import 'tailwindcss';

@theme {
  /* 亮色模式(默认) */
  --color-surface: #ffffff;
  --color-surface-secondary: #f5f5f5;
  --color-text-primary: #1a1a1a;
  --color-text-secondary: #6b7280;
  --color-border: #e5e5e5;
}

.dark {
  --color-surface: #1a1a1a;
  --color-surface-secondary: #2d2d2d;
  --color-text-primary: #f5f5f5;
  --color-text-secondary: #b0b0b0;
  --color-border: #404040;
}

使用 prefers-color-scheme 媒体查询自动检测系统偏好,同时允许用户手动切换:

<script is:inline>
  (function () {
    const theme = localStorage.getItem('theme')
    if (!theme) {
      // 跟随系统偏好
      const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches
      if (prefersDark) document.documentElement.classList.add('dark')
    } else if (theme === 'dark') {
      document.documentElement.classList.add('dark')
    }
  })()
</script>

主题切换按钮的逻辑:

<script>
  const html = document.documentElement
  const btn = document.getElementById('theme-toggle')

  btn?.addEventListener('click', () => {
    const next = html.classList.contains('dark') ? 'light' : 'dark'
    html.classList.toggle('dark', next === 'dark')
    localStorage.setItem('theme', next)
  })
</script>

Cloudflare Pages 部署

Astro 构建的静态站点可以部署到 Cloudflare Pages。完整的部署流程如下:

1. 构建项目

bunx astro build

构建产物默认输出到 dist/ 目录。

2. 使用 wrangler CLI 部署

安装 wrangler:

bun add -D wrangler

登录 Cloudflare 账号:

bunx wrangler login

部署到 Cloudflare Pages:

bunx wrangler pages deploy dist/ --project-name=my-docs-site

首次部署需要指定项目名称,后续部署可以省略 --project-name

3. 配置生产域名

部署完成后,wrangler 会输出一个 <project-name>.pages.dev 的预览域名。如果需要绑定自定义域名,可以在 Cloudflare Dashboard 的 Pages 项目设置中配置。

4. CI/CD 自动化

在项目根目录创建 .github/workflows/deploy.yml

name: Deploy to Cloudflare Pages
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: oven-sh/setup-bun@v2
      - run: bun install
      - run: bunx astro build
      - uses: cloudflare/wrangler-action@v3
        with:
          apiToken: ${{ secrets.CF_API_TOKEN }}
          command: pages deploy dist/ --project-name=my-docs-site

构建配置

astro.config.mjs 中可以对构建行为进行调优:

import { defineConfig } from 'astro/config'

export default defineConfig({
  site: 'https://docs.example.com',
  build: {
    // 自定义输出目录
    outDir: './dist',
    // 启用图片压缩
    assets: 'assets',
  },
  vite: {
    plugins: [tailwindcss()],
    build: {
      // CSS 代码分割
      cssCodeSplit: true,
    },
  },
})