Skip to content

配置指南

本指南介绍如何配置 Trae 开发环境,包括项目设置、环境变量、构建配置等。

概述

Trae 提供了灵活的配置系统,允许您根据项目需求自定义开发环境。通过合理的配置,您可以优化开发体验、提高构建性能并确保项目的可维护性。

项目配置

基础配置文件

Trae 项目的主要配置文件是 trae.config.js,位于项目根目录:

javascript
// trae.config.js
export default {
  // 项目基本信息
  name: 'my-awesome-project',
  version: '1.0.0',
  description: 'A modern web application built with Trae',
  
  // 开发服务器配置
  server: {
    port: 3000,
    host: 'localhost',
    https: false,
    proxy: {
      '/api': {
        target: 'http://localhost:8080',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, '')
      }
    },
    cors: {
      origin: ['http://localhost:3000', 'https://myapp.com'],
      credentials: true
    }
  },
  
  // 构建配置
  build: {
    outDir: 'dist',
    sourcemap: true,
    minify: 'terser',
    target: 'es2020',
    rollupOptions: {
      external: ['react', 'react-dom'],
      output: {
        globals: {
          react: 'React',
          'react-dom': 'ReactDOM'
        }
      }
    }
  },
  
  // 插件配置
  plugins: [
    '@trae/plugin-react',
    '@trae/plugin-typescript',
    '@trae/plugin-eslint',
    {
      name: '@trae/plugin-pwa',
      options: {
        registerType: 'autoUpdate',
        workbox: {
          globPatterns: ['**/*.{js,css,html,ico,png,svg}']
        }
      }
    }
  ],
  
  // 环境配置
  env: {
    development: {
      API_URL: 'http://localhost:8080',
      DEBUG: true,
      LOG_LEVEL: 'debug'
    },
    production: {
      API_URL: 'https://api.myapp.com',
      DEBUG: false,
      LOG_LEVEL: 'error'
    }
  },
  
  // 路径别名
  alias: {
    '@': './src',
    '@components': './src/components',
    '@utils': './src/utils',
    '@assets': './src/assets',
    '@styles': './src/styles'
  },
  
  // CSS 配置
  css: {
    preprocessorOptions: {
      scss: {
        additionalData: '@import "@styles/variables.scss";'
      },
      less: {
        modifyVars: {
          'primary-color': '#1890ff',
          'link-color': '#1890ff'
        }
      }
    },
    modules: {
      localsConvention: 'camelCase',
      generateScopedName: '[name]__[local]___[hash:base64:5]'
    }
  },
  
  // 优化配置
  optimizeDeps: {
    include: ['react', 'react-dom', 'lodash'],
    exclude: ['@trae/dev-tools']
  },
  
  // 测试配置
  test: {
    globals: true,
    environment: 'jsdom',
    setupFiles: ['./src/test/setup.ts'],
    coverage: {
      reporter: ['text', 'json', 'html'],
      exclude: [
        'node_modules/',
        'src/test/',
        '**/*.d.ts'
      ]
    }
  }
};

TypeScript 配置

json
// tsconfig.json
{
  "compilerOptions": {
    "target": "ES2020",
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "skipLibCheck": true,
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],
      "@components/*": ["./src/components/*"],
      "@utils/*": ["./src/utils/*"],
      "@assets/*": ["./src/assets/*"],
      "@styles/*": ["./src/styles/*"]
    }
  },
  "include": ["src"],
  "references": [{ "path": "./tsconfig.node.json" }]
}

ESLint 配置

javascript
// .eslintrc.js
module.exports = {
  root: true,
  env: {
    browser: true,
    es2020: true,
    node: true
  },
  extends: [
    'eslint:recommended',
    '@typescript-eslint/recommended',
    'plugin:react-hooks/recommended',
    'plugin:react/recommended',
    'plugin:jsx-a11y/recommended',
    '@trae/eslint-config'
  ],
  ignorePatterns: ['dist', '.eslintrc.js'],
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaVersion: 'latest',
    sourceType: 'module',
    ecmaFeatures: {
      jsx: true
    }
  },
  plugins: [
    'react-refresh',
    '@typescript-eslint',
    'react',
    'react-hooks',
    'jsx-a11y'
  ],
  rules: {
    'react-refresh/only-export-components': [
      'warn',
      { allowConstantExport: true }
    ],
    'react/react-in-jsx-scope': 'off',
    'react/prop-types': 'off',
    '@typescript-eslint/no-unused-vars': 'error',
    '@typescript-eslint/explicit-function-return-type': 'warn',
    'prefer-const': 'error',
    'no-var': 'error'
  },
  settings: {
    react: {
      version: 'detect'
    }
  }
};

Prettier 配置

json
// .prettierrc
{
  "semi": true,
  "trailingComma": "es5",
  "singleQuote": true,
  "printWidth": 80,
  "tabWidth": 2,
  "useTabs": false,
  "bracketSpacing": true,
  "bracketSameLine": false,
  "arrowParens": "avoid",
  "endOfLine": "lf"
}

环境变量

环境变量文件

Trae 支持多种环境变量文件:

bash
# .env - 所有环境的默认值
VITE_APP_TITLE=My Awesome App
VITE_APP_VERSION=1.0.0

# .env.local - 本地环境(被 git 忽略)
VITE_API_KEY=your-secret-api-key
VITE_DATABASE_URL=postgresql://localhost:5432/myapp

# .env.development - 开发环境
VITE_API_URL=http://localhost:8080/api
VITE_DEBUG=true
VITE_LOG_LEVEL=debug

# .env.production - 生产环境
VITE_API_URL=https://api.myapp.com
VITE_DEBUG=false
VITE_LOG_LEVEL=error
VITE_SENTRY_DSN=https://your-sentry-dsn

# .env.test - 测试环境
VITE_API_URL=http://localhost:3001/api
VITE_TEST_DATABASE_URL=postgresql://localhost:5432/myapp_test

环境变量使用

typescript
// src/config/env.ts
interface EnvConfig {
  apiUrl: string;
  debug: boolean;
  logLevel: 'debug' | 'info' | 'warn' | 'error';
  version: string;
  sentryDsn?: string;
}

export const env: EnvConfig = {
  apiUrl: import.meta.env.VITE_API_URL || 'http://localhost:8080/api',
  debug: import.meta.env.VITE_DEBUG === 'true',
  logLevel: (import.meta.env.VITE_LOG_LEVEL as EnvConfig['logLevel']) || 'info',
  version: import.meta.env.VITE_APP_VERSION || '1.0.0',
  sentryDsn: import.meta.env.VITE_SENTRY_DSN
};

// 类型安全的环境变量
interface ImportMetaEnv {
  readonly VITE_API_URL: string;
  readonly VITE_DEBUG: string;
  readonly VITE_LOG_LEVEL: string;
  readonly VITE_APP_VERSION: string;
  readonly VITE_SENTRY_DSN?: string;
}

interface ImportMeta {
  readonly env: ImportMetaEnv;
}

环境变量验证

typescript
// src/config/validation.ts
import { z } from 'zod';

const envSchema = z.object({
  VITE_API_URL: z.string().url(),
  VITE_DEBUG: z.enum(['true', 'false']).default('false'),
  VITE_LOG_LEVEL: z.enum(['debug', 'info', 'warn', 'error']).default('info'),
  VITE_APP_VERSION: z.string().min(1),
  VITE_SENTRY_DSN: z.string().url().optional()
});

export function validateEnv(): void {
  try {
    envSchema.parse(import.meta.env);
  } catch (error) {
    console.error('❌ Invalid environment variables:', error);
    process.exit(1);
  }
}

// 在应用启动时调用
validateEnv();

构建配置

多环境构建

javascript
// scripts/build.js
import { build } from 'vite';
import { resolve } from 'path';

const environments = ['development', 'staging', 'production'];

async function buildForEnvironment(env) {
  console.log(`🏗️  Building for ${env} environment...`);
  
  await build({
    mode: env,
    build: {
      outDir: `dist/${env}`,
      sourcemap: env !== 'production',
      minify: env === 'production' ? 'terser' : false,
      rollupOptions: {
        input: {
          main: resolve(__dirname, '../index.html'),
          admin: resolve(__dirname, '../admin.html')
        }
      }
    },
    define: {
      __BUILD_TIME__: JSON.stringify(new Date().toISOString()),
      __ENVIRONMENT__: JSON.stringify(env)
    }
  });
  
  console.log(`✅ Build completed for ${env}`);
}

// 构建所有环境
for (const env of environments) {
  await buildForEnvironment(env);
}

代码分割配置

javascript
// trae.config.js
export default {
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          // 将 React 相关库打包到单独的 chunk
          react: ['react', 'react-dom'],
          
          // 将路由相关库打包到单独的 chunk
          router: ['react-router-dom'],
          
          // 将 UI 库打包到单独的 chunk
          ui: ['antd', '@ant-design/icons'],
          
          // 将工具库打包到单独的 chunk
          utils: ['lodash', 'dayjs', 'axios'],
          
          // 动态分割大型库
          vendor: (id) => {
            if (id.includes('node_modules')) {
              // 将大于 500KB 的包单独打包
              const packageName = id.split('node_modules/')[1].split('/')[0];
              const largePackages = ['monaco-editor', 'echarts', 'three'];
              
              if (largePackages.includes(packageName)) {
                return packageName;
              }
              
              return 'vendor';
            }
          }
        },
        
        // 文件命名策略
        chunkFileNames: (chunkInfo) => {
          const facadeModuleId = chunkInfo.facadeModuleId
            ? chunkInfo.facadeModuleId.split('/').pop().replace('.js', '')
            : 'chunk';
          return `js/${facadeModuleId}-[hash].js`;
        },
        
        assetFileNames: (assetInfo) => {
          const info = assetInfo.name.split('.');
          const ext = info[info.length - 1];
          
          if (/\.(png|jpe?g|gif|svg|webp|ico)$/i.test(assetInfo.name)) {
            return `images/[name]-[hash][extname]`;
          }
          
          if (/\.(woff2?|eot|ttf|otf)$/i.test(assetInfo.name)) {
            return `fonts/[name]-[hash][extname]`;
          }
          
          if (/\.(css)$/i.test(assetInfo.name)) {
            return `css/[name]-[hash][extname]`;
          }
          
          return `assets/[name]-[hash][extname]`;
        }
      }
    }
  }
};

开发服务器配置

代理配置

javascript
// trae.config.js
export default {
  server: {
    proxy: {
      // 代理 API 请求
      '/api': {
        target: 'http://localhost:8080',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, ''),
        configure: (proxy, options) => {
          proxy.on('error', (err, req, res) => {
            console.log('proxy error', err);
          });
          proxy.on('proxyReq', (proxyReq, req, res) => {
            console.log('Sending Request to the Target:', req.method, req.url);
          });
          proxy.on('proxyRes', (proxyRes, req, res) => {
            console.log('Received Response from the Target:', proxyRes.statusCode, req.url);
          });
        }
      },
      
      // 代理 WebSocket
      '/ws': {
        target: 'ws://localhost:8080',
        ws: true,
        changeOrigin: true
      },
      
      // 代理静态资源
      '/uploads': {
        target: 'http://localhost:9000',
        changeOrigin: true
      }
    },
    
    // 中间件配置
    middlewares: [
      // 自定义中间件
      (req, res, next) => {
        if (req.url === '/api/health') {
          res.statusCode = 200;
          res.setHeader('Content-Type', 'application/json');
          res.end(JSON.stringify({ status: 'ok', timestamp: Date.now() }));
          return;
        }
        next();
      }
    ]
  }
};

热重载配置

javascript
// trae.config.js
export default {
  server: {
    hmr: {
      port: 24678,
      overlay: true
    },
    
    // 文件监听配置
    watch: {
      ignored: ['**/node_modules/**', '**/dist/**'],
      include: ['src/**/*', 'public/**/*'],
      usePolling: false, // 在某些系统上可能需要设置为 true
      interval: 100
    }
  },
  
  // 插件配置
  plugins: [
    {
      name: 'custom-hmr',
      handleHotUpdate(ctx) {
        // 自定义热更新逻辑
        if (ctx.file.endsWith('.env')) {
          console.log('Environment file changed, restarting server...');
          ctx.server.restart();
          return [];
        }
        
        if (ctx.file.includes('config')) {
          console.log('Config file changed, full reload...');
          ctx.server.ws.send({
            type: 'full-reload'
          });
          return [];
        }
      }
    }
  ]
};

插件配置

官方插件

javascript
// trae.config.js
import { defineConfig } from 'trae';
import react from '@trae/plugin-react';
import typescript from '@trae/plugin-typescript';
import pwa from '@trae/plugin-pwa';
import { visualizer } from '@trae/plugin-visualizer';

export default defineConfig({
  plugins: [
    // React 插件
    react({
      include: '**/*.{jsx,tsx}',
      babel: {
        plugins: [
          ['import', { libraryName: 'antd', style: true }]
        ]
      }
    }),
    
    // TypeScript 插件
    typescript({
      check: true,
      include: ['src/**/*'],
      exclude: ['node_modules', 'dist']
    }),
    
    // PWA 插件
    pwa({
      registerType: 'autoUpdate',
      includeAssets: ['favicon.ico', 'apple-touch-icon.png'],
      manifest: {
        name: 'My Awesome App',
        short_name: 'MyApp',
        description: 'A modern web application',
        theme_color: '#ffffff',
        background_color: '#ffffff',
        display: 'standalone',
        icons: [
          {
            src: 'pwa-192x192.png',
            sizes: '192x192',
            type: 'image/png'
          },
          {
            src: 'pwa-512x512.png',
            sizes: '512x512',
            type: 'image/png'
          }
        ]
      },
      workbox: {
        globPatterns: ['**/*.{js,css,html,ico,png,svg}'],
        runtimeCaching: [
          {
            urlPattern: /^https:\/\/api\.myapp\.com\/.*/i,
            handler: 'NetworkFirst',
            options: {
              cacheName: 'api-cache',
              expiration: {
                maxEntries: 10,
                maxAgeSeconds: 60 * 60 * 24 * 365 // 1 year
              },
              cacheableResponse: {
                statuses: [0, 200]
              }
            }
          }
        ]
      }
    }),
    
    // 构建分析插件
    visualizer({
      filename: 'dist/stats.html',
      open: true,
      gzipSize: true,
      brotliSize: true
    })
  ]
});

自定义插件

javascript
// plugins/custom-plugin.js
export function customPlugin(options = {}) {
  return {
    name: 'custom-plugin',
    
    // 插件配置
    configResolved(config) {
      this.isProduction = config.command === 'build';
    },
    
    // 构建开始
    buildStart(options) {
      console.log('🚀 Build started with custom plugin');
    },
    
    // 转换代码
    transform(code, id) {
      if (id.includes('special-file.js')) {
        // 自定义代码转换
        return {
          code: code.replace(/OLD_PATTERN/g, 'NEW_PATTERN'),
          map: null
        };
      }
    },
    
    // 生成文件
    generateBundle(options, bundle) {
      // 生成额外的文件
      this.emitFile({
        type: 'asset',
        fileName: 'build-info.json',
        source: JSON.stringify({
          buildTime: new Date().toISOString(),
          version: process.env.npm_package_version,
          environment: process.env.NODE_ENV
        }, null, 2)
      });
    },
    
    // 开发服务器配置
    configureServer(server) {
      server.middlewares.use('/api/custom', (req, res, next) => {
        if (req.method === 'GET') {
          res.setHeader('Content-Type', 'application/json');
          res.end(JSON.stringify({ message: 'Custom API endpoint' }));
        } else {
          next();
        }
      });
    }
  };
}

性能优化配置

依赖预构建

javascript
// trae.config.js
export default {
  optimizeDeps: {
    // 强制预构建的依赖
    include: [
      'react',
      'react-dom',
      'react-router-dom',
      'antd',
      'lodash',
      'dayjs'
    ],
    
    // 排除预构建的依赖
    exclude: [
      '@trae/dev-tools',
      'some-esm-only-package'
    ],
    
    // 自定义 esbuild 选项
    esbuildOptions: {
      target: 'es2020',
      supported: {
        'top-level-await': true
      }
    },
    
    // 强制重新预构建
    force: false
  },
  
  // 构建优化
  build: {
    // 启用/禁用 CSS 代码分割
    cssCodeSplit: true,
    
    // 构建后是否生成 source map
    sourcemap: false,
    
    // chunk 大小警告的限制(以 kbs 为单位)
    chunkSizeWarningLimit: 500,
    
    // 自定义底层的 Rollup 打包配置
    rollupOptions: {
      // 确保外部化处理那些你不想打包进库的依赖
      external: ['react', 'react-dom'],
      
      output: {
        // 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
        globals: {
          react: 'React',
          'react-dom': 'ReactDOM'
        }
      }
    },
    
    // 自定义构建的 Terser 选项
    terserOptions: {
      compress: {
        drop_console: true,
        drop_debugger: true
      }
    }
  }
};

缓存配置

javascript
// trae.config.js
export default {
  cacheDir: 'node_modules/.trae',
  
  server: {
    // 强制依赖预构建
    force: false
  },
  
  build: {
    // 启用/禁用 gzip 压缩大小报告
    reportCompressedSize: false,
    
    // 启用构建缓存
    cache: {
      type: 'filesystem',
      cacheDirectory: 'node_modules/.cache/trae'
    }
  }
};

部署配置

静态部署

javascript
// deploy/static.js
import { execSync } from 'child_process';
import { copyFileSync, mkdirSync } from 'fs';
import { resolve } from 'path';

// 构建项目
execSync('npm run build', { stdio: 'inherit' });

// 复制静态文件
const staticFiles = [
  '_redirects',
  '_headers',
  'robots.txt',
  'sitemap.xml'
];

staticFiles.forEach(file => {
  try {
    copyFileSync(
      resolve(`public/${file}`),
      resolve(`dist/${file}`)
    );
    console.log(`✅ Copied ${file}`);
  } catch (error) {
    console.log(`⚠️  ${file} not found, skipping`);
  }
});

console.log('🚀 Static deployment ready!');

Docker 配置

dockerfile
# Dockerfile
FROM node:18-alpine as builder

WORKDIR /app

# 复制 package 文件
COPY package*.json ./

# 安装依赖
RUN npm ci --only=production

# 复制源代码
COPY . .

# 构建应用
RUN npm run build

# 生产镜像
FROM nginx:alpine

# 复制构建结果
COPY --from=builder /app/dist /usr/share/nginx/html

# 复制 nginx 配置
COPY nginx.conf /etc/nginx/nginx.conf

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]
nginx
# nginx.conf
server {
    listen 80;
    server_name localhost;
    root /usr/share/nginx/html;
    index index.html;
    
    # 启用 gzip 压缩
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json;
    
    # 静态资源缓存
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
    
    # HTML 文件不缓存
    location ~* \.html$ {
        expires -1;
        add_header Cache-Control "no-cache, no-store, must-revalidate";
    }
    
    # SPA 路由支持
    location / {
        try_files $uri $uri/ /index.html;
    }
    
    # API 代理
    location /api/ {
        proxy_pass http://backend:8080/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

最佳实践

配置文件组织

project/
├── config/
│   ├── base.config.js          # 基础配置
│   ├── development.config.js   # 开发环境配置
│   ├── production.config.js    # 生产环境配置
│   └── test.config.js          # 测试环境配置
├── scripts/
│   ├── build.js               # 构建脚本
│   ├── deploy.js              # 部署脚本
│   └── dev.js                 # 开发脚本
└── trae.config.js             # 主配置文件

配置验证

javascript
// config/validation.js
import Joi from 'joi';

const configSchema = Joi.object({
  server: Joi.object({
    port: Joi.number().port().default(3000),
    host: Joi.string().default('localhost'),
    https: Joi.boolean().default(false)
  }),
  
  build: Joi.object({
    outDir: Joi.string().default('dist'),
    sourcemap: Joi.boolean().default(true),
    minify: Joi.string().valid('terser', 'esbuild', false).default('terser')
  }),
  
  env: Joi.object().pattern(
    Joi.string(),
    Joi.object().unknown(true)
  )
});

export function validateConfig(config) {
  const { error, value } = configSchema.validate(config, {
    allowUnknown: true,
    stripUnknown: false
  });
  
  if (error) {
    throw new Error(`Configuration validation failed: ${error.message}`);
  }
  
  return value;
}

配置合并

javascript
// trae.config.js
import { defineConfig, mergeConfig } from 'trae';
import baseConfig from './config/base.config.js';
import { validateConfig } from './config/validation.js';

const envConfigs = {
  development: () => import('./config/development.config.js'),
  production: () => import('./config/production.config.js'),
  test: () => import('./config/test.config.js')
};

export default defineConfig(async ({ command, mode }) => {
  // 加载环境特定配置
  const envConfig = envConfigs[mode]
    ? (await envConfigs[mode]()).default
    : {};
  
  // 合并配置
  const config = mergeConfig(baseConfig, envConfig);
  
  // 验证配置
  const validatedConfig = validateConfig(config);
  
  console.log(`🔧 Loaded configuration for ${mode} mode`);
  
  return validatedConfig;
});

通过合理的配置管理,您可以确保 Trae 项目在不同环境下都能稳定运行,同时保持良好的开发体验和构建性能。

您的终极 AI 驱动 IDE 学习指南