简介:本文详细探讨在 Nuxt.js 项目中如何通过环境变量、动态配置和插件机制实现请求域名的灵活管理,涵盖基础配置、动态切换、安全防护及生产环境部署等核心场景。
在 Nuxt.js 项目开发中,请求域名的动态管理是构建可扩展服务的关键环节。无论是应对多环境部署需求,还是实现 API 服务的灵活切换,合理配置请求域名变量都能显著提升开发效率与系统稳定性。本文将从基础配置到进阶方案,系统解析 Nuxt.js 中实现请求域名动态化的技术路径。
Nuxt.js 内置对环境变量的支持,通过 .env 文件与 runtimeConfig 机制,开发者可轻松实现不同环境的域名隔离。
在项目根目录创建以下文件:
.env # 默认环境变量(不推荐存储敏感信息).env.development # 开发环境.env.production # 生产环境.env.staging # 预发布环境
每个文件采用 KEY=VALUE 格式定义变量,例如:
# .env.productionAPI_BASE_URL=https://api.prod.example.comAUTH_SERVICE_URL=https://auth.prod.example.com
在 nuxt.config.js 中通过 runtimeConfig 暴露环境变量:
export default defineNuxtConfig({runtimeConfig: {apiBaseUrl: process.env.API_BASE_URL || 'https://api.default.com',authServiceUrl: process.env.AUTH_SERVICE_URL || 'https://auth.default.com'}})
前端代码通过 useRuntimeConfig() 钩子获取配置:
const config = useRuntimeConfig()const fetchData = async () => {const res = await $fetch(`${config.apiBaseUrl}/data`)// ...}
优势:
注意事项:
当项目需要支持多租户或动态服务路由时,静态环境变量无法满足需求,此时需采用更灵活的动态配置机制。
创建 plugins/domain-manager.ts:
export default defineNuxtPlugin((nuxtApp) => {const config = useRuntimeConfig()// 默认域名映射const domainMap = {api: config.apiBaseUrl,auth: config.authServiceUrl,cdn: process.env.CDN_URL || 'https://cdn.default.com'}// 动态设置方法const setDomain = (service: keyof typeof domainMap, url: string) => {domainMap[service] = url}// 获取完整URLconst getFullUrl = (service: keyof typeof domainMap, path: string) => {return `${domainMap[service]}${path}`}nuxtApp.provide('domain', {setDomain,getFullUrl,domains: domainMap})})
组件中使用示例:
const { $domain } = useNuxtApp()// 获取配置域名const apiUrl = $domain.getFullUrl('api', '/users')// 动态修改域名(需权限控制)if (process.server && user.isAdmin) {$domain.setDomain('api', 'https://api.custom.com')}
结合中间件实现路由级域名控制:
// middleware/domain-router.tsexport default defineNuxtRouteMiddleware((to) => {const config = useRuntimeConfig()const { $domain } = useNuxtApp()// 根据路由前缀切换API域名if (to.path.startsWith('/admin')) {$domain.setDomain('api', config.adminApiUrl)} else {$domain.setDomain('api', config.apiBaseUrl)}})
在 nuxt.config.js 中全局注册:
export default defineNuxtConfig({routeRules: {'/**': { middleware: ['domain-router'] }}})
动态域名配置需特别注意安全防护,避免 SSR 泄露和 XSS 攻击。
对于敏感域名,建议通过服务器中间件动态注入:
// server/api/config.get.tsexport default defineEventHandler(async (event) => {const isProduction = process.env.NODE_ENV === 'production'return {apiUrl: isProduction? process.env.SECURE_API_URL: event.context.config.public.apiBaseUrl}})
客户端获取:
const { data } = await useFetch('/api/config')const apiUrl = data.value?.apiUrl
在 nuxt.config.js 中配置内容安全策略:
export default defineNuxtConfig({nitro: {prerender: {routes: ['/'],csp: {directives: {'connect-src': ["'self'", 'https://api.prod.example.com'],'img-src': ["'self'", 'https://cdn.example.com']}}}}})
动态域名切换可能影响请求性能,需建立监控机制。
在应用启动时预解析关键域名:
// plugins/dns-prefetch.client.tsexport default defineNuxtPlugin(() => {const config = useRuntimeConfig()const domains = [config.apiBaseUrl, config.authServiceUrl]onMounted(() => {domains.forEach(domain => {const link = document.createElement('link')link.rel = 'preconnect'link.href = new URL(domain).origindocument.head.appendChild(link)})})})
封装带重试的 fetch 工具:
// composables/useSafeFetch.tsexport const useSafeFetch = () => {const MAX_RETRIES = 3return async (url: string, options = {}) => {let retryCount = 0while (retryCount < MAX_RETRIES) {try {const res = await $fetch(url, options)return res} catch (err) {retryCount++if (retryCount === MAX_RETRIES) throw errawait new Promise(resolve => setTimeout(resolve, 1000 * retryCount))}}}}
# .env.developmentAPI_BASE_URL=http://localhost:3001AUTH_SERVICE_URL=http://localhost:3002# .env.productionAPI_BASE_URL=https://api.example.comAUTH_SERVICE_URL=https://auth.example.com
主应用配置子应用域名:
// nuxt.config.jsexport default defineNuxtConfig({runtimeConfig: {microFrontends: {dashboard: process.env.DASHBOARD_URL || 'https://dashboard.example.com',analytics: process.env.ANALYTICS_URL || 'https://analytics.example.com'}}})
根据语言切换 API 域名:
// plugins/i18n-domain.tsexport default defineNuxtPlugin((nuxtApp) => {const { locale } = useI18n()const { $domain } = useNuxtApp()watch(locale, (newLocale) => {const baseUrl = newLocale === 'zh'? 'https://api.cn.example.com': 'https://api.example.com'$domain.setDomain('api', baseUrl)})})
变量未生效
.env 文件是否在 .gitignore 中 nuxt.config.js 中 runtimeConfig 键名匹配 process.env 中可用 跨域问题
nuxt.config.js 中配置代理:
export default defineNuxtConfig({nitro: {devProxy: {'/api': {target: 'http://localhost:3001',changeOrigin: true}}}})
SSR 泄露
publicRuntimeConfig 暴露时,确保只在客户端使用 process.server 判断执行环境 建议集成 Sentry 监控域名解析错误:
// plugins/sentry.tsimport * as Sentry from '@sentry/vue'export default defineNuxtPlugin((nuxtApp) => {Sentry.init({dsn: process.env.SENTRY_DSN,integrations: [new Sentry.Integrations.BrowserTracing({routingInstrumentation: Sentry.vueRouterInstrumentation(useRouter())})]})// 捕获请求错误const originalFetch = globalThis.fetchglobalThis.fetch = async (...args) => {try {return await originalFetch.apply(this, args)} catch (err) {Sentry.captureException(err, {tags: {endpoint: new URL(args[0] as string).hostname}})throw err}}})
随着 Nuxt 3 的普及,域名管理可结合以下新特性:
Nitro 服务器插件
通过 server/plugins/ 目录实现更细粒度的请求拦截
Web Standards 集成
利用 Import Maps 动态加载不同域名的模块
Service Worker 缓存
对稳定域名实施持久化缓存策略
Edge Computing
结合 Cloudflare Workers 等边缘计算实现地域级域名路由
通过系统化的域名变量管理,Nuxt.js 应用可获得更高的灵活性和可维护性。开发者应根据项目规模选择合适的方案,从小型项目的环境变量到大型系统的动态路由控制,逐步构建健壮的域名管理体系。