Nuxt.js 动态请求域名管理:环境变量与运行时配置全解析

一、环境变量配置:静态域名的基础管理

在Nuxt.js项目中,环境变量是管理请求域名的最基础方式。通过.env文件与runtimeConfig的配合,可以实现开发、测试、生产环境的域名隔离。

1.1 基础环境变量配置

在项目根目录创建.env.development.env.production等文件:

  1. # .env.development
  2. API_BASE_URL=http://dev-api.example.com
  3. # .env.production
  4. API_BASE_URL=https://api.example.com

nuxt.config.ts中通过runtimeConfig暴露变量:

  1. export default defineNuxtConfig({
  2. runtimeConfig: {
  3. apiBaseUrl: process.env.API_BASE_URL || 'http://localhost:3000',
  4. public: {
  5. // 公开环境变量(客户端可访问)
  6. publicApiUrl: process.env.PUBLIC_API_URL
  7. }
  8. }
  9. })

1.2 类型安全的变量使用

推荐使用TypeScript接口定义环境变量类型:

  1. // types/env.d.ts
  2. interface NuxtRuntimeConfig {
  3. apiBaseUrl: string
  4. public: {
  5. publicApiUrl: string
  6. }
  7. }
  8. declare module '#app' {
  9. interface NuxtApp {
  10. $config: NuxtRuntimeConfig
  11. }
  12. }

在组件中通过useRuntimeConfig()获取:

  1. <script setup lang="ts">
  2. const config = useRuntimeConfig()
  3. const fetchData = async () => {
  4. const res = await $fetch(`${config.apiBaseUrl}/data`)
  5. // ...
  6. }
  7. </script>

二、动态域名切换:运行时的高级控制

当需要根据用户选择、地理位置或多租户系统动态切换域名时,需要更灵活的解决方案。

2.1 插件实现动态域名

创建plugins/dynamic-domain.ts

  1. export default defineNuxtPlugin((nuxtApp) => {
  2. // 从本地存储/Cookie获取域名
  3. const storedDomain = useState('selectedDomain')
  4. nuxtApp.provide('dynamicApi', {
  5. get: async (endpoint: string) => {
  6. const baseUrl = storedDomain.value || nuxtApp.$config.apiBaseUrl
  7. return await $fetch(`${baseUrl}${endpoint}`)
  8. }
  9. })
  10. })

组件中使用:

  1. <script setup>
  2. const { $dynamicApi } = useNuxtApp()
  3. const data = await $dynamicApi.get('/user')
  4. </script>

2.2 服务端渲染适配方案

对于SSR场景,需通过headerscookies传递域名信息:

  1. // server/api/proxy.get.ts
  2. export default defineEventHandler(async (event) => {
  3. const domain = getCookie(event, 'selected_domain') ||
  4. process.env.API_BASE_URL
  5. const { path } = await readBody(event)
  6. return await $fetch(`${domain}${path}`)
  7. })

三、多域名架构实践

3.1 子域名路由配置

nuxt.config.ts中配置路由与域名的映射:

  1. export default defineNuxtConfig({
  2. nitro: {
  3. routeRules: {
  4. '/tenant/**': {
  5. prerender: false,
  6. // 根据tenantId动态设置域名
  7. handler: async (event) => {
  8. const tenantId = event.context.params.tenantId
  9. const domain = getTenantDomain(tenantId) // 自定义逻辑
  10. event.node.res.setHeader('X-API-Domain', domain)
  11. }
  12. }
  13. }
  14. }
  15. })

3.2 代理层集成方案

对于复杂系统,建议通过Nginx反向代理实现域名路由:

  1. server {
  2. listen 80;
  3. server_name ~^(?<tenant>.+)\.example\.com$;
  4. location /api {
  5. proxy_pass http://$tenant-api.internal;
  6. }
  7. }

四、安全与最佳实践

4.1 安全注意事项

  1. 敏感信息保护:避免在客户端暴露内部API域名
  2. CORS配置:动态域名需正确设置Access-Control-Allow-Origin
  3. HTTPS强制:生产环境必须使用HTTPS

4.2 性能优化建议

  1. 域名预热:提前建立DNS连接
  2. 连接复用:合理配置HTTP Keep-Alive
  3. CDN集成:静态资源使用独立域名

4.3 错误处理机制

  1. // composables/useApi.ts
  2. export const useApi = () => {
  3. const config = useRuntimeConfig()
  4. const fetchWithRetry = async (url: string, retries = 3) => {
  5. try {
  6. return await $fetch(url, {
  7. baseURL: config.apiBaseUrl
  8. })
  9. } catch (err) {
  10. if (retries > 0) {
  11. await new Promise(resolve => setTimeout(resolve, 1000))
  12. return fetchWithRetry(url, retries - 1)
  13. }
  14. throw err
  15. }
  16. }
  17. return { fetchWithRetry }
  18. }

五、测试与调试技巧

5.1 单元测试实现

  1. // tests/units/api.test.ts
  2. import { setup } from '@nuxt/test-utils'
  3. describe('API Domain', () => {
  4. setup({
  5. runtimeConfig: {
  6. apiBaseUrl: 'http://test-api'
  7. }
  8. })
  9. it('should use correct domain', async () => {
  10. const { $config } = await nuxt.vueApp
  11. expect($config.apiBaseUrl).toBe('http://test-api')
  12. })
  13. })

5.2 调试工具推荐

  1. Nuxt DevTools:查看运行时环境变量
  2. Postman:测试不同域名的API响应
  3. Wireshark:分析网络请求的域名解析过程

六、进阶场景解决方案

6.1 多环境CDN配置

  1. // nuxt.config.ts
  2. export default defineNuxtConfig({
  3. nitro: {
  4. storage: {
  5. cdn: {
  6. driver: 'fs',
  7. base: './dist/cdn'
  8. }
  9. }
  10. },
  11. runtimeConfig: {
  12. cdnBaseUrl: process.env.CDN_BASE_URL || '/_nuxt'
  13. }
  14. })

6.2 混合静态与动态域名

  1. <script setup>
  2. const isStatic = import.meta.env.SSR
  3. const baseUrl = isStatic
  4. ? useRuntimeConfig().public.staticApiUrl
  5. : useRuntimeConfig().apiBaseUrl
  6. </script>

通过以上方案,开发者可以构建出既灵活又安全的Nuxt.js域名管理系统。实际项目中,建议根据团队规模和业务复杂度选择合适的实现方式,通常环境变量+动态插件的组合可以满足80%以上的场景需求。对于超大规模应用,建议结合服务网格和API网关实现更精细的流量管理。