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 合并。
