Vercel 部署 Astro 完整教學|2025 內容網站最佳選擇

Vercel 部署 Astro 完整教學|2025 內容網站最佳選擇

Astro 是 2025 年最受歡迎的內容網站框架之一。

零 JavaScript 預設、極快的載入速度、支援多框架整合。

部署到 Vercel,讓你的內容網站飛快。

這篇文章教你如何把 Astro 網站部署到 Vercel。


為什麼選擇 Astro + Vercel?

Astro 的優勢

優勢 說明
零 JS 預設 只在需要時載入 JavaScript
Islands 架構 部分互動、部分靜態
框架不限 可以用 React、Vue、Svelte
內容優先 為內容網站而生
超快效能 Lighthouse 滿分

Vercel 的加成

  • 全球 CDN 加速
  • 自動 HTTPS
  • Preview 部署
  • 免費額度充足

專案準備

Astro 專案結構

my-astro-site/
├── public/
│   └── favicon.svg
├── src/
│   ├── components/
│   ├── layouts/
│   │   └── Layout.astro
│   ├── pages/
│   │   ├── index.astro
│   │   └── about.astro
│   └── content/
│       └── blog/
│           └── first-post.md
├── astro.config.mjs
└── package.json

package.json

{
  "name": "my-astro-site",
  "scripts": {
    "dev": "astro dev",
    "build": "astro build",
    "preview": "astro preview"
  },
  "dependencies": {
    "astro": "^4.5.0"
  }
}

本機測試

# 執行 build
npm run build

# 預覽
npm run preview

輸出模式選擇

Static(預設)

所有頁面在 build 時生成。

// astro.config.mjs
import { defineConfig } from 'astro/config';

export default defineConfig({
  output: 'static', // 預設值
});

適合: 部落格、文件網站、作品集

Hybrid

部分靜態、部分動態。

// astro.config.mjs
import { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel/serverless';

export default defineConfig({
  output: 'hybrid',
  adapter: vercel(),
});
---
// 預設靜態,可以選擇性使用 SSR
export const prerender = false; // 這個頁面使用 SSR
---

Server(SSR)

所有頁面都是動態渲染。

// astro.config.mjs
import { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel/serverless';

export default defineConfig({
  output: 'server',
  adapter: vercel(),
});

安裝 Vercel Adapter

安裝

npm install @astrojs/vercel

設定 Adapter

// astro.config.mjs
import { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel/serverless';

export default defineConfig({
  output: 'server', // 或 'hybrid'
  adapter: vercel(),
});

Adapter 選項

import vercel from '@astrojs/vercel/serverless';

export default defineConfig({
  output: 'server',
  adapter: vercel({
    // 啟用 ISR
    isr: true,

    // 設定 function 區域
    functionPerRoute: false,

    // 排除靜態資源
    excludeFiles: ['./src/some-file.js'],
  }),
});

部署到 Vercel

方法一:從 GitHub 部署

步驟一:推送到 GitHub

git init
git add .
git commit -m "Initial commit"
gh repo create my-astro-site --public --source=. --push

步驟二:連接 Vercel

  1. 前往 vercel.com
  2. 點擊 Add NewProject
  3. 選擇 Repository
  4. 點擊 Import

步驟三:確認設定

Vercel 自動偵測 Astro:

設定項目
Framework Astro
Build Command npm run build
Output Directory dist

方法二:Vercel CLI

npm install -g vercel
vercel login
vercel

環境變數

在 Astro 使用

公開變數(會暴露給前端):

# .env
PUBLIC_API_URL=https://api.example.com
---
// 伺服器端
const apiUrl = import.meta.env.PUBLIC_API_URL;
---

<script>
  // 客戶端
  const apiUrl = import.meta.env.PUBLIC_API_URL;
</script>

私密變數(只在伺服器端):

# .env
API_SECRET=your-secret-key
---
// 只在伺服器端可用
const secret = import.meta.env.API_SECRET;
---

在 Vercel 設定

  1. 專案 Settings → Environment Variables
  2. 新增變數
Name: PUBLIC_API_URL
Value: https://api.example.com

內容集合

設定內容集合

// src/content/config.ts
import { defineCollection, z } from 'astro:content';

const blog = defineCollection({
  type: 'content',
  schema: z.object({
    title: z.string(),
    date: z.date(),
    description: z.string(),
    tags: z.array(z.string()).optional(),
  }),
});

export const collections = { blog };

建立內容

---
title: "我的第一篇文章"
date: 2025-01-15
description: "這是文章描述"
tags: ["astro", "vercel"]
---

# 我的第一篇文章

這是內容...

顯示內容

---
// src/pages/blog/[slug].astro
import { getCollection } from 'astro:content';

export async function getStaticPaths() {
  const posts = await getCollection('blog');
  return posts.map(post => ({
    params: { slug: post.slug },
    props: { post },
  }));
}

const { post } = Astro.props;
const { Content } = await post.render();
---

<Layout title={post.data.title}>
  <h1>{post.data.title}</h1>
  <time>{post.data.date.toLocaleDateString()}</time>
  <Content />
</Layout>

Islands 架構

什麼是 Islands?

Astro 使用 Islands 架構:

  • 頁面大部分是靜態 HTML
  • 互動元件是「島嶼」
  • 只在需要時載入 JavaScript

使用 React 元件

npm install @astrojs/react react react-dom
// astro.config.mjs
import { defineConfig } from 'astro/config';
import react from '@astrojs/react';

export default defineConfig({
  integrations: [react()],
});
---
import Counter from '../components/Counter.jsx';
---

<Counter client:load />

客戶端指令

指令 說明
client:load 頁面載入後立即載入
client:idle 瀏覽器閒置時載入
client:visible 元件進入視窗時載入
client:media 符合媒體查詢時載入
client:only 只在客戶端渲染
<!-- 延遲載入,提升效能 -->
<HeavyChart client:visible />

<!-- 手機才載入 -->
<MobileMenu client:media="(max-width: 768px)" />

API 端點

建立 API 端點

// src/pages/api/hello.ts
import type { APIRoute } from 'astro';

export const GET: APIRoute = async () => {
  return new Response(
    JSON.stringify({ message: 'Hello!' }),
    {
      status: 200,
      headers: { 'Content-Type': 'application/json' },
    }
  );
};

POST 請求

// src/pages/api/contact.ts
import type { APIRoute } from 'astro';

export const POST: APIRoute = async ({ request }) => {
  const data = await request.json();

  // 處理表單...

  return new Response(
    JSON.stringify({ success: true }),
    { status: 200 }
  );
};

動態路由

// src/pages/api/users/[id].ts
import type { APIRoute } from 'astro';

export const GET: APIRoute = async ({ params }) => {
  const { id } = params;

  return new Response(
    JSON.stringify({ userId: id }),
    { status: 200 }
  );
};

效能優化

圖片優化

---
import { Image } from 'astro:assets';
import myImage from '../assets/photo.jpg';
---

<Image
  src={myImage}
  alt="描述"
  width={800}
  height={600}
  format="webp"
  loading="lazy"
/>

使用 View Transitions

---
// src/layouts/Layout.astro
import { ViewTransitions } from 'astro:transitions';
---

<html>
  <head>
    <ViewTransitions />
  </head>
  <body>
    <slot />
  </body>
</html>

預載入

---
import { prefetch } from 'astro:prefetch';
---

<a href="/about" data-astro-prefetch>關於我們</a>

設定快取

// vercel.json
{
  "headers": [
    {
      "source": "/_astro/(.*)",
      "headers": [
        {
          "key": "Cache-Control",
          "value": "public, max-age=31536000, immutable"
        }
      ]
    }
  ]
}

常見問題排解

問題一:Build 失敗

錯誤訊息:

Cannot use import statement outside a module

解決方法:

確認 astro.config.mjs 使用 .mjs 副檔名。

問題二:SSR 頁面 404

可能原因: 沒有安裝 Adapter

解決方法:

npm install @astrojs/vercel
// astro.config.mjs
import vercel from '@astrojs/vercel/serverless';

export default defineConfig({
  output: 'server',
  adapter: vercel(),
});

問題三:環境變數讀不到

檢查項目:

  1. 公開變數是否有 PUBLIC_ 前綴
  2. 是否重新部署了
  3. Vercel 是否有設定

問題四:React 元件不渲染

可能原因: 忘記加 client: 指令

<!-- ❌ 不會互動 -->
<Counter />

<!-- ✅ 會互動 -->
<Counter client:load />

問題五:內容集合錯誤

錯誤訊息:

Content collections must be in src/content

解決方法:

確認目錄結構:

src/
└── content/
    ├── config.ts  ← 必須有這個
    └── blog/
        └── post.md

Sitemap 和 SEO

安裝 Sitemap

npm install @astrojs/sitemap
// astro.config.mjs
import sitemap from '@astrojs/sitemap';

export default defineConfig({
  site: 'https://example.com',
  integrations: [sitemap()],
});

設定 SEO

---
// src/components/SEO.astro
const { title, description, image } = Astro.props;
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
---

<title>{title}</title>
<meta name="description" content={description} />
<link rel="canonical" href={canonicalURL} />
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:image" content={image} />

部署檢查清單

部署前

  • [ ] npm run build 成功
  • [ ] 本機預覽正常
  • [ ] 環境變數已設定
  • [ ] Adapter 正確安裝(如果用 SSR)
  • [ ] 內容集合沒有錯誤

部署後

  • [ ] 頁面正常顯示
  • [ ] 互動元件正常運作
  • [ ] API 端點可訪問
  • [ ] 圖片載入正常
  • [ ] SEO meta 正確

常見問題 FAQ

Q1:Static 和 SSR 怎麼選?

選擇 Static 選擇 SSR
部落格 動態內容
文件網站 需要認證
作品集 即時資料
內容不常更新 個人化內容

大多數情況,Static 就夠了

Q2:Astro 適合什麼專案?

  • 部落格和內容網站
  • 行銷頁面
  • 文件網站
  • 作品集

不適合:

  • 高度互動的應用
  • 即時應用

Q3:可以混用 React 和 Vue 嗎?

可以!這是 Astro 的特色:

npm install @astrojs/react @astrojs/vue
---
import ReactComponent from './ReactComponent.jsx';
import VueComponent from './VueComponent.vue';
---

<ReactComponent client:load />
<VueComponent client:load />

Q4:Astro 部署免費嗎?

是的,Vercel 免費方案足夠大多數 Astro 網站。

Q5:如何更新已發布的內容?

重新推送到 GitHub,Vercel 自動重新部署。

或使用 Vercel CLI:

vercel --prod

Vercel 部署失敗?

Build Error、環境變數、自訂網域,我們幫你快速排除問題。

解決 Vercel 問題


延伸閱讀

分享文章:
V

VibeFix

專門解決 AI Vibe Coding 後的疑難雜症,讓你的專案順利上線。

這篇文章有幫到你嗎?

如果還有問題,讓我們直接幫你解決!

聯繫我們