當您運行 npm run generate 生成靜態頁面時,Vite 的代理服務器確實無法使用,因為生成階段是在 Node.js 環境中執行的構建過程。但別擔心,我將為您提供一套完整的解決方案來處理構建階段的跨域問題。
核心解決方案
1. 構建階段:使用服務端中轉 API(推薦)
在構建階段通過 Nuxt 的 server 路由中轉請求,避開跨域限制:
// server/api/products.ts
export default defineEventHandler(async (event) => {// 從環境變量獲取API地址const apiBase = useRuntimeConfig().public.apiBase// 構建階段直接調用API(無跨域問題)return await $fetch(`${apiBase}/products`, {headers: {'Authorization': `Bearer ${process.env.API_TOKEN}`}}).catch(() => ([])) // 添加錯誤處理
})
為什么?server/api/products.ts是服務端中轉 API?
文件位于 server/api 目錄下,這是 Nuxt 3 中定義服務器端 API 的標準位置。
文件名為 products.ts,表示它處理的是與 /api/products 路徑相關的請求
在這個處理函數中,它接收來自客戶端的請求(在構建階段,這個請求來自 Nuxt 的構建進程),然后它自己作為客戶端去請求另一個后端服務(${apiBase}/products)。
這個后端服務可能是你真正的業務 API,可能運行在另一個域名或端口上(比如 http://localhost:3001 或 https://api.example.com)。
在構建階段(npm run generate),Nuxt 是在 Node.js 環境中運行的,所以它直接發起 HTTP 請求(使用 $fetch)到后端服務,這不存在瀏覽器的同源策略限制(跨域問題只存在于瀏覽器中)。
在開發階段,我們通過 Vite 的代理配置(在 nuxt.config.ts 中)將客戶端對 /api/products 的請求代理到真正的后端服務,同樣避免了瀏覽器的跨域問題。
2. 頁面組件中調用中轉 API
<!-- pages/products.vue -->
<script setup>
// 構建時調用的中轉API(不存在跨域問題)
const { data: products } = await useAsyncData('products',() => $fetch('/api/products')
)
</script>
?當 Nuxt.js 執行 $fetch('/api/products') 時,它會自動匹配并調用 server/api/products.ts 中定義的中轉 API 處理程序??。這是一個 Nuxt.js 的核心約定機制。
詳細的路徑匹配規則:
??目錄結構映射??:
- 所有放在?
server/api/
?目錄下的 .ts 文件都會自動注冊為 API 端點 - 文件路徑直接對應路由路徑:
??具體匹配過程??:
文件路徑 | 對應的API路由 |
server/api/products.ts | /api/products |
server/api/products/index.ts | /api/products |
server/api/products/[id].ts? | ?/api/products/:id |
server/api/categories/featured.ts | ?/api/categories/featured |
??在頁面中調用??:
// 調用以下路徑的API:
$fetch('/api/products') | server/api/products.ts |
$fetch('/api/products/123') | server/api/products/[id].ts |
$fetch('/api/categories/featured') | server/api/categories/featured.ts |
處理函數約定??:
- 每個文件必須導出?
default defineEventHandler
?作為請求處理函數 - Nuxt 自動將請求路由到對應的處理程序
- 每個文件必須導出?
// server/api/products.ts
export default defineEventHandler(async (event) => { // 所有對 /api/products 的請求都會到達這里
})
3. 配置環境變量
# .env.production
NUXT_PUBLIC_API_BASE=https://production-api.com
API_TOKEN=your_prod_token# .env.development
NUXT_PUBLIC_API_BASE=http://localhost:3000
4,開發環境 Vite 代理配置
// nuxt.config.ts
export default defineNuxtConfig({vite: {server: {proxy: {// 開發環境代理配置'/api/': {target: process.env.NUXT_PUBLIC_API_BASE || 'http://localhost:3000',changeOrigin: true,rewrite: path => path.replace(/^\/api\//, '')}}}},// 通用配置runtimeConfig: {public: {apiBase: process.env.NUXT_PUBLIC_API_BASE}}
})
5.構建階段工作流程詳解
構建流程 (npm run generate)│├─ 1. 加載 nuxt.config.ts│ ? ? 讀取 runtimeConfig.public.apiBase│├─ 2. 掃描 pages/ 目錄│ ? ? 識別出需要使用數據的頁面│├─ 3. 執行頁面中的 useAsyncData/useFetch│ ? ? → 調用 /api/products│ ? ? ? ?↓├─ 4. 路由到 server/api/products.ts│ ? ? → 使用 $fetch 訪問外部 API│ ? ? ? ?↓├─ 5. 獲取數據 → 渲染頁面 → 生成靜態HTML│└─ 6. 輸出靜態文件到 .output/public