在前后端分离的 Nuxt SSR 项目中,调用后端接口的代码通常不写在 **server** 目录中,而是直接写在**页面(pages)或组件(components)**里。
Nuxt 的 server 目录主要用于编写 BFF(Backend For Frontend)层的代理接口或处理纯服务端逻辑。对于前后端分离的架构,前端页面直接请求后端 API 是最标准的做法。
以下是完整的架构说明和代码示例:
1. 标准做法:在页面/组件中直接调用(推荐)
在 Nuxt 3 中,推荐使用 useFetch 或 useAsyncData 组合式函数。它们会自动处理 SSR 时的服务端请求和客户端的水合(Hydration),避免数据重复获取。
文件:**pages/index.vue**
<script setup lang="ts">
// 使用 useFetch 获取后端接口数据
// 这个请求在 SSR 阶段会在服务端执行,在客户端交互时会在浏览器执行
const { data, pending, error } = await useFetch('https://api.example.com/users', {
method: 'GET',
headers: {
'Authorization': 'Bearer YOUR_TOKEN'
}
})
</script>
<template>
<div>
<h1>用户列表</h1>
<div v-if="pending">加载中…</div>
<div v-else-if="error">加载失败</div>
<ul v-else>
<li v-for="user in data" :key="user.id">{{ user.name }}</li>
</ul>
</div>
</template>
2. 进阶做法:封装请求工具(适合中大型项目)
为了统一管理请求头(如 Token)、基础 URL 和错误处理,通常会在 utils 或 composables 目录下封装一个请求函数。
文件:**utils/request.ts**
export const useApi = () => {
const config = useRuntimeConfig()
// 封装一个支持 SSR 的请求函数
const fetchApi = async (url: string, options: any = {}) => {
return await useFetch(`${config.public.apiBase}${url}`, {
…options,
headers: {
…options.headers,
// 可以在这里统一注入 Token
}
})
}
return { fetchApi }
}
文件:**pages/users.vue**
<script setup lang="ts">
const { fetchApi } = useApi()
// 调用封装好的请求
const { data: users } = await fetchApi('/users', { method: 'GET' })
</script>
<template>
<div>
<pre>{{ users }}</pre>
</div>
</template>
3. 什么时候需要写在 server 目录中?
虽然前后端分离通常直接调用后端,但在以下场景中,你需要在 server/api 中写代码:
- 隐藏敏感信息:后端 API 的密钥(Secret Key)不能暴露给浏览器,必须在服务端代理转发。
- 跨域问题:通过 Nuxt 服务端代理请求后端,解决浏览器的 CORS 限制。
- 数据聚合:前端需要同时调用多个后端接口,可以在 server 层聚合后返回给前端,减少请求次数。
文件:**server/api/users.ts**** (Nuxt 服务端代理)**
export default defineEventHandler(async (event) => {
// 在服务端请求真实的后端 API
const data = await $fetch('https://private-api.example.com/users', {
headers: {
'X-API-KEY': process.env.SECRET_API_KEY // 敏感信息放在服务端
}
})
return data
})
文件:**pages/index.vue**** (前端调用 Nuxt 代理接口)**
<script setup lang="ts">
// 注意:这里请求的是本地的 /api/users,Nuxt 会自动在服务端代理到真实后端
const { data } = await useFetch('/api/users')
</script>
总结对比
| 直接调用 | pages/ 或 components/ | 标准前后端分离,无敏感信息 | 简单直接,利用 Nuxt 自动 SSR 优化 |
| 代理调用 | server/api/ | 需要隐藏密钥、解决跨域、数据聚合 | 安全性高,前端代码更简洁 |
核心建议:如果你的后端接口不需要隐藏密钥且没有跨域问题,直接在 **pages** 或 **composables** 中使用 **useFetch** 调用是最高效的做法。






