Skip to content

部署指南

本指南介绍如何将 Trae 应用程序部署到各种平台和环境,包括云服务、容器化部署和传统服务器部署。

概述

Trae 支持多种部署方式,从简单的静态网站托管到复杂的容器化微服务架构。选择合适的部署策略取决于您的应用需求、团队规模和预算考虑。

构建准备

生产构建

在部署之前,确保您的应用已经过生产优化:

bash
# 安装依赖
npm ci --production

# 运行测试
npm test

# 构建生产版本
npm run build

# 预览构建结果
npm run preview

构建优化

javascript
// trae.config.js - 生产构建配置
export default {
  build: {
    // 输出目录
    outDir: 'dist',
    
    // 启用压缩
    minify: 'terser',
    
    // 禁用 source map(可选)
    sourcemap: false,
    
    // 代码分割
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ['react', 'react-dom'],
          router: ['react-router-dom'],
          ui: ['antd']
        }
      }
    },
    
    // Terser 配置
    terserOptions: {
      compress: {
        drop_console: true,
        drop_debugger: true
      }
    }
  },
  
  // 环境变量
  define: {
    __BUILD_TIME__: JSON.stringify(new Date().toISOString()),
    __VERSION__: JSON.stringify(process.env.npm_package_version)
  }
};

环境配置

bash
# .env.production
VITE_API_URL=https://api.myapp.com
VITE_CDN_URL=https://cdn.myapp.com
VITE_SENTRY_DSN=https://your-sentry-dsn
VITE_ANALYTICS_ID=GA_MEASUREMENT_ID

静态网站部署

Vercel 部署

  1. 安装 Vercel CLI

    bash
    npm i -g vercel
  2. 配置 vercel.json

    json
    {
      "version": 2,
      "builds": [
        {
          "src": "package.json",
          "use": "@vercel/static-build",
          "config": {
            "distDir": "dist"
          }
        }
      ],
      "routes": [
        {
          "src": "/api/(.*)",
          "dest": "/api/$1"
        },
        {
          "src": "/(.*)",
          "dest": "/index.html"
        }
      ],
      "headers": [
        {
          "source": "/static/(.*)",
          "headers": [
            {
              "key": "Cache-Control",
              "value": "public, max-age=31536000, immutable"
            }
          ]
        }
      ],
      "env": {
        "VITE_API_URL": "@api_url",
        "VITE_SENTRY_DSN": "@sentry_dsn"
      }
    }
  3. 部署命令

    bash
    # 部署到预览环境
    vercel
    
    # 部署到生产环境
    vercel --prod

Netlify 部署

  1. 配置 netlify.toml

    toml
    [build]
      publish = "dist"
      command = "npm run build"
    
    [build.environment]
      NODE_VERSION = "18"
    
    [[redirects]]
      from = "/api/*"
      to = "https://api.myapp.com/:splat"
      status = 200
      force = true
    
    [[redirects]]
      from = "/*"
      to = "/index.html"
      status = 200
    
    [[headers]]
      for = "/static/*"
      [headers.values]
        Cache-Control = "public, max-age=31536000, immutable"
    
    [[headers]]
      for = "/*.html"
      [headers.values]
        Cache-Control = "no-cache"
  2. 环境变量设置

    bash
    # 通过 Netlify CLI 设置
    netlify env:set VITE_API_URL https://api.myapp.com
    netlify env:set VITE_SENTRY_DSN https://your-sentry-dsn

GitHub Pages 部署

  1. GitHub Actions 工作流

    yaml
    # .github/workflows/deploy.yml
    name: Deploy to GitHub Pages
    
    on:
      push:
        branches: [main]
      workflow_dispatch:
    
    permissions:
      contents: read
      pages: write
      id-token: write
    
    concurrency:
      group: "pages"
      cancel-in-progress: false
    
    jobs:
      build:
        runs-on: ubuntu-latest
        steps:
          - name: Checkout
            uses: actions/checkout@v4
          
          - name: Setup Node.js
            uses: actions/setup-node@v4
            with:
              node-version: '18'
              cache: 'npm'
          
          - name: Install dependencies
            run: npm ci
          
          - name: Build
            run: npm run build
            env:
              VITE_API_URL: ${{ secrets.API_URL }}
              VITE_SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
          
          - name: Setup Pages
            uses: actions/configure-pages@v4
          
          - name: Upload artifact
            uses: actions/upload-pages-artifact@v3
            with:
              path: './dist'
    
      deploy:
        environment:
          name: github-pages
          url: ${{ steps.deployment.outputs.page_url }}
        runs-on: ubuntu-latest
        needs: build
        steps:
          - name: Deploy to GitHub Pages
            id: deployment
            uses: actions/deploy-pages@v4
  2. 配置 base 路径

    javascript
    // trae.config.js
    export default {
      base: process.env.NODE_ENV === 'production' ? '/repository-name/' : '/'
    };

容器化部署

Docker 部署

  1. 多阶段 Dockerfile

    dockerfile
    # 构建阶段
    FROM node:18-alpine as builder
    
    WORKDIR /app
    
    # 复制 package 文件
    COPY package*.json ./
    
    # 安装依赖
    RUN npm ci --only=production && npm cache clean --force
    
    # 复制源代码
    COPY . .
    
    # 构建应用
    RUN npm run build
    
    # 生产阶段
    FROM nginx:alpine
    
    # 安装 dumb-init
    RUN apk add --no-cache dumb-init
    
    # 创建非 root 用户
    RUN addgroup -g 1001 -S nodejs
    RUN adduser -S nextjs -u 1001
    
    # 复制构建结果
    COPY --from=builder /app/dist /usr/share/nginx/html
    
    # 复制 nginx 配置
    COPY nginx.conf /etc/nginx/nginx.conf
    
    # 设置权限
    RUN chown -R nextjs:nodejs /usr/share/nginx/html
    RUN chown -R nextjs:nodejs /var/cache/nginx
    RUN chown -R nextjs:nodejs /var/log/nginx
    RUN chown -R nextjs:nodejs /etc/nginx/conf.d
    RUN touch /var/run/nginx.pid
    RUN chown -R nextjs:nodejs /var/run/nginx.pid
    
    USER nextjs
    
    EXPOSE 8080
    
    ENTRYPOINT ["dumb-init", "--"]
    CMD ["nginx", "-g", "daemon off;"]
  2. Nginx 配置

    nginx
    # nginx.conf
    worker_processes auto;
    error_log /var/log/nginx/error.log warn;
    pid /var/run/nginx.pid;
    
    events {
        worker_connections 1024;
    }
    
    http {
        include /etc/nginx/mime.types;
        default_type application/octet-stream;
        
        log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                        '$status $body_bytes_sent "$http_referer" '
                        '"$http_user_agent" "$http_x_forwarded_for"';
        
        access_log /var/log/nginx/access.log main;
        
        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;
        
        # Gzip 压缩
        gzip on;
        gzip_vary on;
        gzip_min_length 1024;
        gzip_proxied any;
        gzip_comp_level 6;
        gzip_types
            text/plain
            text/css
            text/xml
            text/javascript
            application/json
            application/javascript
            application/xml+rss
            application/atom+xml
            image/svg+xml;
        
        server {
            listen 8080;
            server_name localhost;
            root /usr/share/nginx/html;
            index index.html;
            
            # 安全头
            add_header X-Frame-Options "SAMEORIGIN" always;
            add_header X-XSS-Protection "1; mode=block" always;
            add_header X-Content-Type-Options "nosniff" always;
            add_header Referrer-Policy "no-referrer-when-downgrade" always;
            add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
            
            # 静态资源缓存
            location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
                expires 1y;
                add_header Cache-Control "public, immutable";
                access_log off;
            }
            
            # HTML 文件不缓存
            location ~* \.html$ {
                expires -1;
                add_header Cache-Control "no-cache, no-store, must-revalidate";
            }
            
            # SPA 路由支持
            location / {
                try_files $uri $uri/ /index.html;
            }
            
            # 健康检查
            location /health {
                access_log off;
                return 200 "healthy\n";
                add_header Content-Type text/plain;
            }
        }
    }
  3. Docker Compose

    yaml
    # docker-compose.yml
    version: '3.8'
    
    services:
      app:
        build:
          context: .
          dockerfile: Dockerfile
        ports:
          - "3000:8080"
        environment:
          - NODE_ENV=production
        restart: unless-stopped
        healthcheck:
          test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
          interval: 30s
          timeout: 10s
          retries: 3
        labels:
          - "traefik.enable=true"
          - "traefik.http.routers.app.rule=Host(`myapp.com`)"
          - "traefik.http.routers.app.tls=true"
          - "traefik.http.routers.app.tls.certresolver=letsencrypt"
    
      traefik:
        image: traefik:v2.10
        command:
          - "--api.insecure=true"
          - "--providers.docker=true"
          - "--providers.docker.exposedbydefault=false"
          - "--entrypoints.web.address=:80"
          - "--entrypoints.websecure.address=:443"
          - "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
          - "--certificatesresolvers.letsencrypt.acme.email=admin@myapp.com"
          - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
        ports:
          - "80:80"
          - "443:443"
          - "8080:8080"
        volumes:
          - "/var/run/docker.sock:/var/run/docker.sock:ro"
          - "./letsencrypt:/letsencrypt"

Kubernetes 部署

  1. Deployment 配置

    yaml
    # k8s/deployment.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: trae-app
      labels:
        app: trae-app
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: trae-app
      template:
        metadata:
          labels:
            app: trae-app
        spec:
          containers:
          - name: trae-app
            image: myregistry/trae-app:latest
            ports:
            - containerPort: 8080
            env:
            - name: NODE_ENV
              value: "production"
            - name: API_URL
              valueFrom:
                configMapKeyRef:
                  name: app-config
                  key: api-url
            resources:
              requests:
                memory: "128Mi"
                cpu: "100m"
              limits:
                memory: "256Mi"
                cpu: "200m"
            livenessProbe:
              httpGet:
                path: /health
                port: 8080
              initialDelaySeconds: 30
              periodSeconds: 10
            readinessProbe:
              httpGet:
                path: /health
                port: 8080
              initialDelaySeconds: 5
              periodSeconds: 5
  2. Service 配置

    yaml
    # k8s/service.yaml
    apiVersion: v1
    kind: Service
    metadata:
      name: trae-app-service
    spec:
      selector:
        app: trae-app
      ports:
      - protocol: TCP
        port: 80
        targetPort: 8080
      type: ClusterIP
  3. Ingress 配置

    yaml
    # k8s/ingress.yaml
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: trae-app-ingress
      annotations:
        kubernetes.io/ingress.class: "nginx"
        cert-manager.io/cluster-issuer: "letsencrypt-prod"
        nginx.ingress.kubernetes.io/rewrite-target: /
    spec:
      tls:
      - hosts:
        - myapp.com
        secretName: trae-app-tls
      rules:
      - host: myapp.com
        http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: trae-app-service
                port:
                  number: 80
  4. ConfigMap 配置

    yaml
    # k8s/configmap.yaml
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: app-config
    data:
      api-url: "https://api.myapp.com"
      sentry-dsn: "https://your-sentry-dsn"

云平台部署

AWS 部署

  1. S3 + CloudFront 部署

    bash
    # 安装 AWS CLI
    npm install -g @aws-amplify/cli
    
    # 配置 AWS 凭证
    aws configure
    
    # 创建 S3 存储桶
    aws s3 mb s3://my-trae-app
    
    # 上传构建文件
    aws s3 sync dist/ s3://my-trae-app --delete
    
    # 设置网站配置
    aws s3 website s3://my-trae-app --index-document index.html --error-document index.html
  2. CloudFormation 模板

    yaml
    # cloudformation.yaml
    AWSTemplateFormatVersion: '2010-09-09'
    Description: 'Trae App Infrastructure'
    
    Resources:
      S3Bucket:
        Type: AWS::S3::Bucket
        Properties:
          BucketName: !Sub '${AWS::StackName}-app'
          WebsiteConfiguration:
            IndexDocument: index.html
            ErrorDocument: index.html
          PublicAccessBlockConfiguration:
            BlockPublicAcls: false
            BlockPublicPolicy: false
            IgnorePublicAcls: false
            RestrictPublicBuckets: false
    
      CloudFrontDistribution:
        Type: AWS::CloudFront::Distribution
        Properties:
          DistributionConfig:
            Origins:
            - DomainName: !GetAtt S3Bucket.RegionalDomainName
              Id: S3Origin
              S3OriginConfig:
                OriginAccessIdentity: ''
            Enabled: true
            DefaultRootObject: index.html
            DefaultCacheBehavior:
              TargetOriginId: S3Origin
              ViewerProtocolPolicy: redirect-to-https
              CachePolicyId: 4135ea2d-6df8-44a3-9df3-4b5a84be39ad
            CustomErrorResponses:
            - ErrorCode: 404
              ResponseCode: 200
              ResponsePagePath: /index.html
            - ErrorCode: 403
              ResponseCode: 200
              ResponsePagePath: /index.html

Google Cloud Platform 部署

  1. App Engine 部署

    yaml
    # app.yaml
    runtime: nodejs18
    
    handlers:
    - url: /static
      static_dir: dist/static
      secure: always
    
    - url: /(.*\.(js|css|ico|png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot))$
      static_files: dist/\1
      upload: dist/(.*\.(js|css|ico|png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot))$
      secure: always
    
    - url: /.*
      static_files: dist/index.html
      upload: dist/index.html
      secure: always
    
    env_variables:
      NODE_ENV: production
      API_URL: https://api.myapp.com
  2. Cloud Run 部署

    bash
    # 构建并推送镜像
    gcloud builds submit --tag gcr.io/PROJECT_ID/trae-app
    
    # 部署到 Cloud Run
    gcloud run deploy trae-app \
      --image gcr.io/PROJECT_ID/trae-app \
      --platform managed \
      --region us-central1 \
      --allow-unauthenticated

Azure 部署

  1. Static Web Apps 部署
    yaml
    # .github/workflows/azure-static-web-apps.yml
    name: Azure Static Web Apps CI/CD
    
    on:
      push:
        branches:
          - main
      pull_request:
        types: [opened, synchronize, reopened, closed]
        branches:
          - main
    
    jobs:
      build_and_deploy_job:
        if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed')
        runs-on: ubuntu-latest
        name: Build and Deploy Job
        steps:
          - uses: actions/checkout@v3
            with:
              submodules: true
          - name: Build And Deploy
            id: builddeploy
            uses: Azure/static-web-apps-deploy@v1
            with:
              azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}
              repo_token: ${{ secrets.GITHUB_TOKEN }}
              action: "upload"
              app_location: "/"
              api_location: ""
              output_location: "dist"

持续集成/持续部署 (CI/CD)

GitHub Actions

yaml
# .github/workflows/ci-cd.yml
name: CI/CD Pipeline

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

env:
  NODE_VERSION: '18'
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Run linting
        run: npm run lint
      
      - name: Run tests
        run: npm test -- --coverage
      
      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v3
        with:
          file: ./coverage/lcov.info

  build:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Build application
        run: npm run build
        env:
          VITE_API_URL: ${{ secrets.PROD_API_URL }}
          VITE_SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
      
      - name: Upload build artifacts
        uses: actions/upload-artifact@v3
        with:
          name: dist
          path: dist/

  docker:
    needs: build
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    permissions:
      contents: read
      packages: write
    steps:
      - uses: actions/checkout@v4
      
      - name: Download build artifacts
        uses: actions/download-artifact@v3
        with:
          name: dist
          path: dist/
      
      - name: Log in to Container Registry
        uses: docker/login-action@v2
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      
      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=ref,event=branch
            type=ref,event=pr
            type=sha,prefix={{branch}}-
            type=raw,value=latest,enable={{is_default_branch}}
      
      - name: Build and push Docker image
        uses: docker/build-push-action@v4
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}

  deploy:
    needs: docker
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    environment: production
    steps:
      - name: Deploy to production
        run: |
          echo "Deploying to production..."
          # 这里添加您的部署脚本

GitLab CI/CD

yaml
# .gitlab-ci.yml
stages:
  - test
  - build
  - deploy

variables:
  NODE_VERSION: "18"
  DOCKER_DRIVER: overlay2
  DOCKER_TLS_CERTDIR: "/certs"

cache:
  paths:
    - node_modules/

test:
  stage: test
  image: node:$NODE_VERSION
  script:
    - npm ci
    - npm run lint
    - npm test -- --coverage
  coverage: '/Lines\s*:\s*(\d+\.?\d*)%/'
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage/cobertura-coverage.xml

build:
  stage: build
  image: node:$NODE_VERSION
  script:
    - npm ci
    - npm run build
  artifacts:
    paths:
      - dist/
    expire_in: 1 hour
  only:
    - main

docker:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    - docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:latest
    - docker push $CI_REGISTRY_IMAGE:latest
  only:
    - main

deploy_staging:
  stage: deploy
  script:
    - echo "Deploying to staging..."
    # 添加部署到测试环境的脚本
  environment:
    name: staging
    url: https://staging.myapp.com
  only:
    - develop

deploy_production:
  stage: deploy
  script:
    - echo "Deploying to production..."
    # 添加部署到生产环境的脚本
  environment:
    name: production
    url: https://myapp.com
  when: manual
  only:
    - main

监控和日志

应用监控

javascript
// src/monitoring/sentry.js
import * as Sentry from '@sentry/react';
import { BrowserTracing } from '@sentry/tracing';

Sentry.init({
  dsn: import.meta.env.VITE_SENTRY_DSN,
  environment: import.meta.env.MODE,
  integrations: [
    new BrowserTracing({
      tracingOrigins: ['localhost', /^\//],
    }),
  ],
  tracesSampleRate: 1.0,
  beforeSend(event) {
    // 过滤敏感信息
    if (event.exception) {
      const error = event.exception.values[0];
      if (error.value && error.value.includes('password')) {
        return null;
      }
    }
    return event;
  },
});

export { Sentry };

性能监控

javascript
// src/monitoring/performance.js
export class PerformanceMonitor {
  static init() {
    // Web Vitals 监控
    import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
      getCLS(this.sendToAnalytics);
      getFID(this.sendToAnalytics);
      getFCP(this.sendToAnalytics);
      getLCP(this.sendToAnalytics);
      getTTFB(this.sendToAnalytics);
    });
    
    // 自定义性能指标
    this.measureRouteChanges();
    this.measureAPIRequests();
  }
  
  static sendToAnalytics(metric) {
    // 发送到 Google Analytics
    if (window.gtag) {
      window.gtag('event', metric.name, {
        event_category: 'Web Vitals',
        value: Math.round(metric.name === 'CLS' ? metric.value * 1000 : metric.value),
        event_label: metric.id,
        non_interaction: true,
      });
    }
    
    // 发送到自定义分析服务
    fetch('/api/analytics/performance', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(metric),
    }).catch(console.error);
  }
  
  static measureRouteChanges() {
    let startTime = performance.now();
    
    // 监听路由变化
    window.addEventListener('popstate', () => {
      const duration = performance.now() - startTime;
      this.sendToAnalytics({
        name: 'route_change',
        value: duration,
        id: `route-${Date.now()}`,
      });
      startTime = performance.now();
    });
  }
  
  static measureAPIRequests() {
    const originalFetch = window.fetch;
    
    window.fetch = async (...args) => {
      const startTime = performance.now();
      const response = await originalFetch(...args);
      const duration = performance.now() - startTime;
      
      this.sendToAnalytics({
        name: 'api_request',
        value: duration,
        id: `api-${Date.now()}`,
        url: args[0],
        status: response.status,
      });
      
      return response;
    };
  }
}

安全考虑

内容安全策略 (CSP)

html
<!-- index.html -->
<meta http-equiv="Content-Security-Policy" content="
  default-src 'self';
  script-src 'self' 'unsafe-inline' https://www.googletagmanager.com;
  style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
  font-src 'self' https://fonts.gstatic.com;
  img-src 'self' data: https:;
  connect-src 'self' https://api.myapp.com https://sentry.io;
  frame-ancestors 'none';
  base-uri 'self';
  form-action 'self';
">

环境变量安全

javascript
// scripts/deploy-secrets.js
import { SecretsManager } from 'aws-sdk';

const secretsManager = new SecretsManager({ region: 'us-east-1' });

async function deploySecrets() {
  const secrets = {
    API_KEY: process.env.API_KEY,
    DATABASE_URL: process.env.DATABASE_URL,
    SENTRY_DSN: process.env.SENTRY_DSN,
  };
  
  await secretsManager.createSecret({
    Name: 'trae-app-secrets',
    SecretString: JSON.stringify(secrets),
  }).promise();
  
  console.log('✅ Secrets deployed successfully');
}

deploySecrets().catch(console.error);

故障排除

常见部署问题

  1. 路由问题

    nginx
    # 确保 SPA 路由正确配置
    location / {
        try_files $uri $uri/ /index.html;
    }
  2. 环境变量未生效

    bash
    # 检查环境变量
    echo $VITE_API_URL
    
    # 重新构建
    npm run build
  3. CORS 问题

    javascript
    // 配置代理或后端 CORS
    server: {
      proxy: {
        '/api': 'http://localhost:8080'
      }
    }

部署检查清单

  • [ ] 环境变量配置正确
  • [ ] 构建成功且无错误
  • [ ] 静态资源路径正确
  • [ ] 路由配置支持 SPA
  • [ ] HTTPS 证书配置
  • [ ] 缓存策略设置
  • [ ] 监控和日志配置
  • [ ] 安全头设置
  • [ ] 性能优化启用
  • [ ] 备份和恢复策略

通过遵循这些部署指南,您可以确保 Trae 应用程序在各种环境中稳定、安全、高效地运行。

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