Nuxt.js 配置文件最佳实践完全指南

HTMLPAGE 团队
18 分钟阅读

深入掌握 nuxt.config.ts 的配置技巧,从基础设置到高级优化,学会根据项目需求定制完美的 Nuxt.js 应用配置。

#Nuxt.js #nuxt.config #Vue.js #配置管理 #项目架构

Nuxt.js 配置文件最佳实践完全指南

nuxt.config.ts 概述

nuxt.config.ts 是 Nuxt.js 应用的核心配置文件,控制着应用的各个方面:构建行为、模块加载、运行时配置等。理解并正确配置这个文件,是开发高质量 Nuxt 应用的基础。

nuxt.config.ts 的作用范围:

┌─────────────────────────────────────────────────────────────┐
│                     nuxt.config.ts                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────┐ │
│  │  应用基础   │  │  模块系统   │  │  构建配置          │ │
│  │  - app      │  │  - modules  │  │  - vite            │ │
│  │  - ssr      │  │  - extends  │  │  - nitro           │ │
│  │  - devtools │  │  - plugins  │  │  - postcss         │ │
│  └─────────────┘  └─────────────┘  └─────────────────────┘ │
│                                                             │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────┐ │
│  │  路由配置   │  │  运行时配置 │  │  实验性功能        │ │
│  │  - router   │  │ -runtimeConfig│ │  - experimental   │ │
│  │  - pages    │  │  - appConfig│  │  - features        │ │
│  └─────────────┘  └─────────────┘  └─────────────────────┘ │
│                                                             │
└─────────────────────────────────────────────────────────────┘

基础配置结构

最小配置

// nuxt.config.ts
export default defineNuxtConfig({
  // 兼容性日期
  compatibilityDate: '2024-12-24',
  
  // 开发工具
  devtools: { enabled: true }
})

完整的生产配置框架

// nuxt.config.ts
export default defineNuxtConfig({
  // 兼容性版本
  compatibilityDate: '2024-12-24',
  
  // 开发工具
  devtools: { enabled: process.env.NODE_ENV !== 'production' },
  
  // 应用配置
  app: {},
  
  // 模块
  modules: [],
  
  // 运行时配置
  runtimeConfig: {},
  
  // Vite 配置
  vite: {},
  
  // Nitro 服务器配置
  nitro: {},
  
  // 路由配置
  routeRules: {},
  
  // 实验性功能
  experimental: {}
})

应用配置(app)

基础 App 配置

export default defineNuxtConfig({
  app: {
    // HTML head 配置
    head: {
      charset: 'utf-8',
      viewport: 'width=device-width, initial-scale=1',
      title: '我的网站',
      titleTemplate: '%s - 我的网站',
      
      // Meta 标签
      meta: [
        { name: 'description', content: '网站描述' },
        { name: 'theme-color', content: '#ffffff' },
        { property: 'og:type', content: 'website' },
        { property: 'og:site_name', content: '我的网站' }
      ],
      
      // Link 标签
      link: [
        { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
        { rel: 'apple-touch-icon', href: '/apple-touch-icon.png' },
        { rel: 'manifest', href: '/manifest.json' },
        // 预连接优化
        { rel: 'preconnect', href: 'https://fonts.googleapis.com' },
        { rel: 'dns-prefetch', href: 'https://api.example.com' }
      ],
      
      // Script 标签
      script: [
        // 分析脚本(异步加载)
        {
          src: 'https://analytics.example.com/script.js',
          async: true,
          defer: true
        }
      ],
      
      // HTML 属性
      htmlAttrs: {
        lang: 'zh-CN'
      },
      
      // Body 属性
      bodyAttrs: {
        class: 'antialiased'
      }
    },
    
    // 页面过渡动画
    pageTransition: {
      name: 'page',
      mode: 'out-in'
    },
    
    // 布局过渡动画
    layoutTransition: {
      name: 'layout',
      mode: 'out-in'
    },
    
    // 基础路径(用于子目录部署)
    baseURL: '/',
    
    // CDN URL
    cdnURL: process.env.CDN_URL || ''
  }
})

动态 Head 配置

// 使用函数动态生成 head
export default defineNuxtConfig({
  app: {
    head: () => {
      const isProd = process.env.NODE_ENV === 'production';
      
      return {
        title: isProd ? '生产环境' : '开发环境',
        meta: [
          // 生产环境添加额外的安全头
          ...(isProd ? [
            { 'http-equiv': 'X-UA-Compatible', content: 'IE=edge' },
            { name: 'robots', content: 'index, follow' }
          ] : [
            { name: 'robots', content: 'noindex, nofollow' }
          ])
        ]
      };
    }
  }
})

模块配置(modules)

常用模块配置

export default defineNuxtConfig({
  modules: [
    // UI 框架
    '@nuxt/ui',
    
    // 图片优化
    '@nuxt/image',
    
    // 内容管理
    '@nuxt/content',
    
    // SEO
    '@nuxtjs/seo',
    
    // 国际化
    '@nuxtjs/i18n',
    
    // 分析
    '@nuxtjs/plausible',
    
    // 状态管理
    '@pinia/nuxt',
    
    // 自定义配置的模块
    ['@nuxtjs/google-fonts', {
      families: {
        'Inter': [400, 500, 600, 700]
      },
      display: 'swap',
      prefetch: true,
      preconnect: true
    }]
  ]
})

模块选项的最佳实践

export default defineNuxtConfig({
  modules: [
    '@nuxt/image',
    '@nuxt/content',
    '@nuxtjs/i18n'
  ],
  
  // 推荐:使用顶级配置而不是内联配置
  // 这样更清晰,也便于类型推断
  
  image: {
    // 图片提供商
    provider: 'ipx',
    
    // 图片质量
    quality: 80,
    
    // 预设
    presets: {
      avatar: {
        modifiers: {
          format: 'webp',
          width: 100,
          height: 100,
          fit: 'cover'
        }
      },
      thumbnail: {
        modifiers: {
          format: 'webp',
          width: 300,
          height: 200,
          fit: 'cover'
        }
      }
    },
    
    // 屏幕断点
    screens: {
      xs: 320,
      sm: 640,
      md: 768,
      lg: 1024,
      xl: 1280,
      xxl: 1536
    }
  },
  
  content: {
    // 内容目录
    sources: {
      content: {
        driver: 'fs',
        base: './content'
      }
    },
    
    // Markdown 配置
    markdown: {
      toc: { depth: 3 },
      remarkPlugins: [],
      rehypePlugins: []
    },
    
    // 高亮配置
    highlight: {
      theme: 'github-dark',
      langs: ['javascript', 'typescript', 'vue', 'css', 'html', 'json']
    }
  },
  
  i18n: {
    locales: [
      { code: 'zh', name: '中文', file: 'zh.json' },
      { code: 'en', name: 'English', file: 'en.json' }
    ],
    defaultLocale: 'zh',
    lazy: true,
    langDir: 'locales/',
    strategy: 'prefix_except_default',
    detectBrowserLanguage: {
      useCookie: true,
      cookieKey: 'i18n_redirected',
      fallbackLocale: 'zh'
    }
  }
})

运行时配置(runtimeConfig)

环境变量与运行时配置

export default defineNuxtConfig({
  runtimeConfig: {
    // 仅服务端可访问的配置
    // 敏感信息放这里
    apiSecret: process.env.API_SECRET,
    databaseUrl: process.env.DATABASE_URL,
    
    jwtSecret: process.env.JWT_SECRET,
    
    // 第三方服务密钥
    stripe: {
      secretKey: process.env.STRIPE_SECRET_KEY
    },
    
    // 邮件服务
    mail: {
      host: process.env.MAIL_HOST,
      port: process.env.MAIL_PORT,
      user: process.env.MAIL_USER,
      password: process.env.MAIL_PASSWORD
    },
    
    // 公开的配置(客户端也可访问)
    public: {
      // 网站 URL
      siteUrl: process.env.SITE_URL || 'http://localhost:3000',
      
      // API 基础路径
      apiBase: process.env.API_BASE || '/api',
      
      // 公开的第三方服务 ID
      googleAnalyticsId: process.env.GA_ID,
      stripePublicKey: process.env.STRIPE_PUBLIC_KEY,
      
      // 功能开关
      features: {
        enableComments: process.env.ENABLE_COMMENTS === 'true',
        enableNewsletter: process.env.ENABLE_NEWSLETTER === 'true'
      }
    }
  }
})

在代码中使用运行时配置

// 在 Vue 组件中
<script setup lang="ts">
const config = useRuntimeConfig()

// 客户端和服务端都可以访问
console.log(config.public.siteUrl)
console.log(config.public.apiBase)

// 仅服务端可以访问(在服务端代码中)
// console.log(config.apiSecret) // 仅在服务端有效
</script>

// 在服务端 API 中
// server/api/example.ts
export default defineEventHandler((event) => {
  const config = useRuntimeConfig(event)
  
  // 可以访问私有配置
  const secret = config.apiSecret
  const dbUrl = config.databaseUrl
  
  // 也可以访问公开配置
  const siteUrl = config.public.siteUrl
  
  return { message: 'ok' }
})

Vite 配置

构建优化

export default defineNuxtConfig({
  vite: {
    // 构建目标
    build: {
      // 浏览器兼容性
      target: 'es2020',
      
      // CSS 代码分割
      cssCodeSplit: true,
      
      // 分块策略
      rollupOptions: {
        output: {
          manualChunks: {
            // 第三方库分离
            'vendor-vue': ['vue', 'vue-router'],
            'vendor-utils': ['lodash-es', 'date-fns'],
            'vendor-ui': ['@headlessui/vue', '@heroicons/vue']
          }
        }
      },
      
      // 压缩选项
      minify: 'terser',
      terserOptions: {
        compress: {
          drop_console: process.env.NODE_ENV === 'production',
          drop_debugger: true
        }
      }
    },
    
    // CSS 配置
    css: {
      preprocessorOptions: {
        scss: {
          additionalData: `
            @use "@/assets/styles/variables" as *;
            @use "@/assets/styles/mixins" as *;
          `
        }
      }
    },
    
    // 优化依赖预构建
    optimizeDeps: {
      include: [
        'vue',
        'vue-router',
        '@vueuse/core',
        'pinia'
      ],
      exclude: [
        'some-heavy-package'
      ]
    },
    
    // 服务器配置
    server: {
      hmr: {
        overlay: true
      },
      watch: {
        // 忽略某些文件的监听
        ignored: ['**/node_modules/**', '**/dist/**']
      }
    },
    
    // 插件
    plugins: [
      // 可以添加 Vite 插件
    ]
  }
})

别名配置

import { fileURLToPath } from 'url'
import { dirname, join } from 'path'

const currentDir = dirname(fileURLToPath(import.meta.url))

export default defineNuxtConfig({
  alias: {
    '@': join(currentDir, './'),
    '@components': join(currentDir, './components'),
    '@composables': join(currentDir, './composables'),
    '@utils': join(currentDir, './utils'),
    '@assets': join(currentDir, './assets'),
    '@types': join(currentDir, './types')
  }
})

Nitro 服务器配置

基础服务器配置

export default defineNuxtConfig({
  nitro: {
    // 部署预设
    preset: 'node-server', // 或 'vercel', 'netlify', 'cloudflare' 等
    
    // 压缩响应
    compressPublicAssets: true,
    
    // 存储配置
    storage: {
      cache: {
        driver: 'redis',
        url: process.env.REDIS_URL
      },
      data: {
        driver: 'fs',
        base: './data'
      }
    },
    
    // 定时任务
    scheduledTasks: {
      '0 0 * * *': ['cleanup:old-data']
    },
    
    // 路由规则
    routeRules: {
      // 预渲染静态页面
      '/': { prerender: true },
      '/about': { prerender: true },
      '/blog/**': { prerender: true },
      
      // API 缓存
      '/api/products': { cache: { maxAge: 60 * 60 } }, // 1小时
      '/api/categories': { cache: { maxAge: 60 * 60 * 24 } }, // 1天
      
      // SWR 缓存策略
      '/api/user': { 
        cache: { 
          swr: true, 
          maxAge: 60,
          staleMaxAge: 60 * 60 
        } 
      },
      
      // 代理
      '/legacy-api/**': { proxy: 'https://old-api.example.com/**' },
      
      // 重定向
      '/old-page': { redirect: '/new-page' },
      
      // CORS
      '/api/**': {
        cors: true,
        headers: {
          'Access-Control-Allow-Origin': '*'
        }
      }
    },
    
    // 实验性功能
    experimental: {
      // 启用 WebSocket
      websocket: true,
      
      // 任务队列
      tasks: true
    }
  }
})

预渲染配置

export default defineNuxtConfig({
  nitro: {
    prerender: {
      // 要预渲染的路由
      routes: [
        '/',
        '/about',
        '/contact',
        '/pricing'
      ],
      
      // 爬取发现的链接
      crawlLinks: true,
      
      // 忽略某些路由
      ignore: [
        '/admin',
        '/api'
      ],
      
      // 并发数
      concurrency: 10,
      
      // 失败时的行为
      failOnError: process.env.NODE_ENV === 'production'
    }
  },
  
  // 路由规则中的预渲染
  routeRules: {
    // 动态路由预渲染
    '/products/**': { prerender: true },
    '/blog/**': { prerender: true }
  }
})

环境特定配置

使用 $env 条件配置

export default defineNuxtConfig({
  // 基础配置
  devtools: { enabled: true },
  
  // 开发环境特定配置
  $development: {
    devtools: { enabled: true },
    
    vite: {
      server: {
        hmr: {
          overlay: true
        }
      }
    }
  },
  
  // 生产环境特定配置
  $production: {
    devtools: { enabled: false },
    
    app: {
      head: {
        script: [
          // 只在生产环境加载分析脚本
          { src: 'https://analytics.example.com/script.js', async: true }
        ]
      }
    },
    
    nitro: {
      compressPublicAssets: true
    }
  },
  
  // 测试环境
  $test: {
    ssr: false
  }
})

基于环境变量的配置

const isDev = process.env.NODE_ENV !== 'production'
const isPreview = process.env.NUXT_ENV === 'preview'

export default defineNuxtConfig({
  ssr: !isDev || isPreview,
  
  sourcemap: isDev ? 'hidden' : false,
  
  modules: [
    '@nuxt/ui',
    // 开发时启用的模块
    ...(isDev ? ['@nuxt/devtools'] : []),
    // 生产时启用的模块
    ...(!isDev ? ['@nuxtjs/plausible'] : [])
  ],
  
  vite: {
    build: {
      sourcemap: isDev,
      minify: !isDev
    }
  }
})

性能优化配置

完整的性能优化配置

export default defineNuxtConfig({
  // 启用实验性功能以提升性能
  experimental: {
    // 内联样式
    inlineSSRStyles: true,
    
    // 组件岛屿
    componentIslands: true,
    
    // Payload 提取
    payloadExtraction: true,
    
    // 视图过渡 API
    viewTransition: true,
    
    // 渲染 JSON Payload
    renderJsonPayloads: true
  },
  
  // Vite 性能配置
  vite: {
    build: {
      // 代码分割
      cssCodeSplit: true,
      
      rollupOptions: {
        output: {
          // 优化分块
          manualChunks(id) {
            if (id.includes('node_modules')) {
              // 核心依赖
              if (id.includes('vue') || id.includes('pinia')) {
                return 'vendor-core'
              }
              // UI 库
              if (id.includes('@headlessui') || id.includes('@heroicons')) {
                return 'vendor-ui'
              }
              // 工具库
              return 'vendor-utils'
            }
          }
        }
      }
    },
    
    // 预构建优化
    optimizeDeps: {
      include: ['vue', 'pinia', '@vueuse/core']
    }
  },
  
  // Nitro 性能配置
  nitro: {
    compressPublicAssets: {
      gzip: true,
      brotli: true
    },
    
    // 静态资源缓存
    publicAssets: [{
      dir: 'public',
      maxAge: 60 * 60 * 24 * 365, // 1年
      baseURL: '/'
    }],
    
    // 预渲染
    prerender: {
      crawlLinks: true,
      concurrency: 10
    }
  },
  
  // 路由缓存规则
  routeRules: {
    // 静态页面
    '/': { prerender: true },
    
    // API 缓存
    '/api/static/**': { 
      cache: { maxAge: 60 * 60 * 24 } 
    },
    
    // CDN 缓存
    '/_nuxt/**': { 
      headers: { 
        'cache-control': 'public, max-age=31536000, immutable' 
      } 
    }
  }
})

懒加载和代码分割

export default defineNuxtConfig({
  // 组件自动导入配置
  components: {
    dirs: [
      {
        path: '~/components',
        // 全局组件(立即加载)
        global: false
      },
      {
        path: '~/components/global',
        global: true
      }
    ]
  },
  
  // 插件配置
  plugins: [
    // 客户端插件(懒加载)
    { src: '~/plugins/analytics.client.ts', mode: 'client' },
    // 服务端插件
    { src: '~/plugins/auth.server.ts', mode: 'server' }
  ],
  
  // 实验性:组件岛屿
  experimental: {
    componentIslands: true
  }
})

调试和开发体验

开发工具配置

export default defineNuxtConfig({
  // DevTools
  devtools: {
    enabled: true,
    
    timeline: {
      enabled: true
    }
  },
  
  // 开发服务器
  devServer: {
    port: 3000,
    host: '0.0.0.0',
    
    // HTTPS(本地开发)
    https: false
  },
  
  // TypeScript 配置
  typescript: {
    strict: true,
    typeCheck: true,
    
    shim: false
  },
  
  // 源码映射
  sourcemap: {
    server: true,
    client: true
  },
  
  // 调试信息
  debug: process.env.DEBUG === 'true',
  
  // 日志级别
  logLevel: process.env.DEBUG === 'true' ? 'verbose' : 'info'
})

安全配置

安全头和 CSP

export default defineNuxtConfig({
  // 安全模块
  modules: ['nuxt-security'],
  
  security: {
    headers: {
      // 内容安全策略
      contentSecurityPolicy: {
        'base-uri': ["'self'"],
        'default-src': ["'self'"],
        'script-src': ["'self'", "'unsafe-inline'", 'https://trusted-cdn.com'],
        'style-src': ["'self'", "'unsafe-inline'"],
        'img-src': ["'self'", 'data:', 'https:'],
        'font-src': ["'self'", 'https://fonts.gstatic.com'],
        'connect-src': ["'self'", 'https://api.example.com'],
        'frame-ancestors': ["'none'"]
      },
      
      // 其他安全头
      crossOriginEmbedderPolicy: 'require-corp',
      crossOriginOpenerPolicy: 'same-origin',
      crossOriginResourcePolicy: 'same-origin',
      permissionsPolicy: {
        camera: [],
        microphone: [],
        geolocation: []
      },
      strictTransportSecurity: {
        maxAge: 31536000,
        includeSubdomains: true,
        preload: true
      },
      xContentTypeOptions: 'nosniff',
      xFrameOptions: 'DENY',
      xXSSProtection: '1; mode=block'
    },
    
    // 请求大小限制
    requestSizeLimiter: {
      maxRequestSizeInBytes: 2000000, // 2MB
      maxUploadFileRequestInBytes: 8000000 // 8MB
    },
    
    // 速率限制
    rateLimiter: {
      tokensPerInterval: 100,
      interval: 60000 // 1分钟
    }
  }
})

完整的生产配置示例

// nuxt.config.ts
import { fileURLToPath } from 'url'
import { dirname, join } from 'path'

const currentDir = dirname(fileURLToPath(import.meta.url))
const isDev = process.env.NODE_ENV !== 'production'

export default defineNuxtConfig({
  // 基础配置
  compatibilityDate: '2024-12-24',
  devtools: { enabled: isDev },
  
  // 应用配置
  app: {
    head: {
      charset: 'utf-8',
      viewport: 'width=device-width, initial-scale=1',
      title: '我的应用',
      titleTemplate: '%s - 我的应用',
      htmlAttrs: { lang: 'zh-CN' },
      meta: [
        { name: 'description', content: '应用描述' },
        { name: 'theme-color', content: '#4f46e5' }
      ],
      link: [
        { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
      ]
    },
    pageTransition: { name: 'page', mode: 'out-in' }
  },
  
  // 模块
  modules: [
    '@nuxt/ui',
    '@nuxt/image',
    '@nuxt/content',
    '@pinia/nuxt',
    '@vueuse/nuxt',
    '@nuxtjs/i18n'
  ],
  
  // 运行时配置
  runtimeConfig: {
    apiSecret: process.env.API_SECRET,
    public: {
      siteUrl: process.env.SITE_URL || 'http://localhost:3000',
      apiBase: process.env.API_BASE || '/api'
    }
  },
  
  // Vite
  vite: {
    build: {
      target: 'es2020',
      cssCodeSplit: true,
      rollupOptions: {
        output: {
          manualChunks: {
            'vendor-vue': ['vue', 'vue-router', 'pinia'],
            'vendor-utils': ['@vueuse/core']
          }
        }
      }
    },
    css: {
      preprocessorOptions: {
        scss: {
          additionalData: '@use "@/assets/styles/variables" as *;'
        }
      }
    }
  },
  
  // Nitro
  nitro: {
    compressPublicAssets: true,
    prerender: {
      routes: ['/', '/about'],
      crawlLinks: true
    }
  },
  
  // 路由规则
  routeRules: {
    '/': { prerender: true },
    '/api/**': { cors: true },
    '/_nuxt/**': { 
      headers: { 'cache-control': 'public, max-age=31536000, immutable' }
    }
  },
  
  // 实验性功能
  experimental: {
    payloadExtraction: true,
    renderJsonPayloads: true,
    viewTransition: true
  },
  
  // TypeScript
  typescript: {
    strict: true,
    typeCheck: isDev
  }
})

最佳实践总结

nuxt.config.ts 最佳实践:

组织结构:
✓ 按功能区块组织配置
✓ 使用顶级模块配置而非内联配置
✓ 敏感信息放在 runtimeConfig 中
✓ 公开配置放在 runtimeConfig.public 中

性能优化:
✓ 启用适当的实验性功能
✓ 配置合理的代码分割策略
✓ 使用预渲染加速静态页面
✓ 配置适当的缓存策略

环境管理:
✓ 使用 $development/$production 条件配置
✓ 通过环境变量控制功能开关
✓ 生产环境禁用调试工具
✓ 开发环境启用详细日志

安全性:
✓ 配置安全头(CSP 等)
✓ 私密信息不暴露到客户端
✓ 使用 HTTPS
✓ 配置请求限制和速率限制

可维护性:
✓ 添加必要的注释
✓ 使用 TypeScript 获取类型提示
✓ 定期更新依赖和配置
✓ 保持配置文件简洁清晰

正确配置 nuxt.config.ts 是构建高质量 Nuxt.js 应用的基础。随着项目的发展,定期审查和优化配置文件,确保它始终符合项目的需求。