⚠️ Alpha内测版本警告:此为早期内部构建版本,尚不完整且可能存在错误,欢迎大家提Issue反馈问题或建议
Skip to content

9.5.3 项目能打包成功吗——构建验证:生产构建成功性检查

开发环境能跑不代表生产环境能跑——每次合并前都必须验证生产构建。

构建验证的必要性

Next.js 构建配置

typescript
// next.config.ts
import type { NextConfig } from 'next';

const nextConfig: NextConfig = {
  // 严格模式
  reactStrictMode: true,
  
  // TypeScript 严格检查
  typescript: {
    ignoreBuildErrors: false,
  },
  
  // ESLint 检查
  eslint: {
    ignoreDuringBuilds: false,
  },
  
  // 输出配置
  output: 'standalone',
  
  // 实验性功能
  experimental: {
    typedRoutes: true,
  },
};

export default nextConfig;

CI 构建配置

yaml
# .github/workflows/ci.yml
jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      
      - run: npm ci
      
      - name: Build
        run: npm run build
        env:
          # 构建时需要的环境变量
          NEXT_PUBLIC_API_URL: https://api.example.com
          DATABASE_URL: ${{ secrets.DATABASE_URL }}
      
      - name: Check bundle size
        run: |
          du -sh .next/static
          du -sh .next/server

环境变量验证

typescript
// lib/env.ts
import { z } from 'zod';

const envSchema = z.object({
  DATABASE_URL: z.string().url(),
  NEXT_PUBLIC_API_URL: z.string().url(),
  JWT_SECRET: z.string().min(32),
});

// 构建时验证
export const env = envSchema.parse({
  DATABASE_URL: process.env.DATABASE_URL,
  NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL,
  JWT_SECRET: process.env.JWT_SECRET,
});
typescript
// next.config.ts
import './lib/env'; // 构建时验证环境变量

构建产物检查

yaml
# .github/workflows/ci.yml
- name: Verify build output
  run: |
    # 检查关键文件存在
    test -f .next/BUILD_ID
    test -d .next/static
    test -d .next/server
    
    # 检查构建大小
    SIZE=$(du -sm .next | cut -f1)
    if [ "$SIZE" -gt 500 ]; then
      echo "Warning: Build size ${SIZE}MB exceeds 500MB"
    fi

构建缓存

yaml
# .github/workflows/ci.yml
- name: Cache Next.js build
  uses: actions/cache@v3
  with:
    path: |
      .next/cache
    key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**/*.ts', '**/*.tsx') }}
    restore-keys: |
      ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-
      ${{ runner.os }}-nextjs-

常见构建错误

1. 环境变量缺失

typescript
// ❌ 构建时报错
const apiUrl = process.env.NEXT_PUBLIC_API_URL!;
// 如果未设置,构建会通过但运行时出错

// ✅ 构建时验证
if (!process.env.NEXT_PUBLIC_API_URL) {
  throw new Error('Missing NEXT_PUBLIC_API_URL');
}

2. 服务端/客户端代码混淆

typescript
// ❌ 客户端代码使用服务端模块
'use client';
import { prisma } from '@/lib/prisma'; // 构建失败

// ✅ 通过 API 调用
'use client';
const data = await fetch('/api/users').then(r => r.json());

3. 动态导入问题

typescript
// ❌ 构建时找不到模块
const Component = dynamic(() => import('./Component'), {
  ssr: false,
});

// ✅ 确保路径正确且模块存在
const Component = dynamic(() => import('@/components/Component'), {
  ssr: false,
  loading: () => <Skeleton />,
});

构建分析

json
// package.json
{
  "scripts": {
    "build": "next build",
    "build:analyze": "ANALYZE=true next build"
  }
}
typescript
// next.config.ts
import bundleAnalyzer from '@next/bundle-analyzer';

const withBundleAnalyzer = bundleAnalyzer({
  enabled: process.env.ANALYZE === 'true',
});

export default withBundleAnalyzer(nextConfig);

本节小结

构建验证是部署前的最后一道检查。确保 next.config.ts 不忽略 TypeScript 和 ESLint 错误,在 CI 中设置必要的环境变量,验证构建产物完整性。构建失败必须阻断 PR 合并。