fix(build): lazy initialize Resend to prevent build failures
ci/woodpecker/push/woodpecker Pipeline failed

The real root cause of CI build failures was NOT Turbopack, but
Resend initialization at module level without API key.

Problem:
- Resend was initialized at module level: const resend = new Resend(process.env.RESEND_API_KEY)
- During build, Next.js collects page data and imports all modules
- If RESEND_API_KEY is not set, Resend throws error: 'Missing API key'
- This caused build to fail with 'Failed to collect page data for /api/contact'

Solution:
- Implement lazy initialization pattern for Resend
- Only initialize Resend when actually needed (when sending emails)
- Add proper error handling if API key is missing

Changes:
- src/app/api/contact/route.ts: Add getResend() function with lazy init
- src/app/(marketing)/contact/actions.ts: Add getResend() function with lazy init

This allows the build to succeed even without RESEND_API_KEY in CI,
while still requiring it at runtime when actually sending emails.
This commit is contained in:
张翔
2026-03-30 10:44:10 +08:00
parent dccea17ac5
commit 8b7cc15362
2 changed files with 28 additions and 4 deletions
+14 -2
View File
@@ -3,9 +3,21 @@
import { Resend } from 'resend';
import { z } from 'zod';
const resend = new Resend(process.env.RESEND_API_KEY);
const companyEmail = process.env.COMPANY_EMAIL || 'contact@novalon.cn';
let resend: Resend | null = null;
function getResend(): Resend {
if (!resend) {
const apiKey = process.env.RESEND_API_KEY;
if (!apiKey) {
throw new Error('RESEND_API_KEY environment variable is not set');
}
resend = new Resend(apiKey);
}
return resend;
}
const contactFormSchema = z.object({
name: z.string().min(2, '姓名至少需要2个字符'),
phone: z.string().regex(/^1[3-9]\d{9}$/, '请输入有效的手机号码'),
@@ -244,7 +256,7 @@ export async function submitContactForm(
`;
try {
const { data: emailData, error } = await resend.emails.send({
const { data: emailData, error } = await getResend().emails.send({
from: '睿新致远官网 <onboarding@resend.dev>',
to: [companyEmail],
subject: `📧 ${data.subject} - ${data.name}`,
+14 -2
View File
@@ -3,9 +3,21 @@ import { Resend } from 'resend';
import { z } from 'zod';
import { SecurityMiddleware } from '@/lib/security/middleware';
const resend = new Resend(process.env.RESEND_API_KEY);
const companyEmail = process.env.COMPANY_EMAIL || 'contact@novalon.cn';
let resend: Resend | null = null;
function getResend(): Resend {
if (!resend) {
const apiKey = process.env.RESEND_API_KEY;
if (!apiKey) {
throw new Error('RESEND_API_KEY environment variable is not set');
}
resend = new Resend(apiKey);
}
return resend;
}
let securityMiddleware = new SecurityMiddleware();
export function setSecurityMiddleware(middleware: SecurityMiddleware) {
@@ -108,7 +120,7 @@ export async function POST(request: NextRequest) {
</html>
`;
const result = await resend.emails.send({
const result = await getResend().emails.send({
from: '睿新致远官网 <onboarding@resend.dev>',
to: [companyEmail],
subject: `${sanitizedData.subject} - ${sanitizedData.name}`,