You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Qwik应用部署Vercel时Nodemailer导致构建失败求助

Qwik部署Vercel时Nodemailer构建失败的解决方案

问题描述

部署Qwik应用到Vercel时,只要导入nodemailer就触发构建失败,报错信息如下:

[commonjs--resolver] Cannot bundle Node.js built-in "events" imported from "node_modules/nodemailer/lib/mailer/index.js". Consider disabling ssr.noExternal or remove the built-in dependency.

已尝试操作:

  • 将nodemailer升级至最新版本(6.9.4)
  • 在Vite配置中添加ssr.noExternal
  • 移除nodemailer后构建成功,但业务需要保留该库用于邮件发送

依赖版本:Qwik 1.2.6、Nodemailer 6.9.4、Vercel CLI 29.1.1、Node.js v18.17.1


解决方案

1. 仅在服务器端API端点中使用Nodemailer

Nodemailer是Node.js专属库,绝对不能在客户端组件中导入。正确的做法是将邮件发送逻辑封装到Qwik的服务器端API端点中,客户端通过HTTP请求调用该端点触发邮件发送。

示例:创建src/routes/api/send-email.ts端点

import { type RequestHandler } from '@builder.io/qwik-city';
import nodemailer from 'nodemailer';

export const onPost: RequestHandler = async ({ request, response }) => {
  const { to, subject, text } = await request.json();

  // 配置Nodemailer传输器
  const transporter = nodemailer.createTransport({
    service: 'Gmail', // 替换为你的邮件服务
    auth: {
      user: process.env.EMAIL_USER,
      pass: process.env.EMAIL_PASS
    }
  });

  const mailOptions = {
    from: process.env.EMAIL_USER,
    to,
    subject,
    text
  };

  try {
    await transporter.sendMail(mailOptions);
    response.status = 200;
    response.json({ success: true });
  } catch (error) {
    response.status = 500;
    response.json({ success: false, error: (error as Error).message });
  }
};

客户端通过fetch调用该API:

// 客户端组件中
const sendEmail = async () => {
  const res = await fetch('/api/send-email', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      to: 'recipient@example.com',
      subject: 'Test Email',
      text: 'Hello from Qwik + Vercel!'
    })
  });
  const data = await res.json();
  console.log(data);
};

2. 正确配置Vite的SSR外部依赖

如果因业务需要在SSR场景下使用Nodemailer,调整vite.config.ts的SSR配置,将Nodemailer及其依赖的Node.js内置模块标记为外部依赖,避免Vite尝试打包它们:

import { defineConfig } from 'vite';
import { qwikVite } from '@builder.io/qwik/optimizer';
import { qwikCity } from '@builder.io/qwik-city/vite';

export default defineConfig(() => {
  return {
    plugins: [qwikCity(), qwikVite()],
    ssr: {
      // 将Nodemailer和Node.js内置模块设为外部依赖,由运行时Node环境提供
      external: ['nodemailer', 'events', 'stream', 'crypto']
    }
  };
});

注意:ssr.external与ssr.noExternal作用相反——前者告知Vite无需打包指定模块,后者强制打包。此处使用external更符合Node.js库的运行逻辑。

3. 确认Vercel构建配置

确保Vercel使用正确的构建命令和输出目录,可在项目根目录创建vercel.json:

{
  "buildCommand": "npm run build",
  "outputDirectory": "dist"
}

同时在Vercel控制台的项目设置中,确认运行环境为Node.js 18.x,与本地开发版本保持一致。

4. 用环境变量存储敏感信息

避免在代码中硬编码邮箱账号、密码等敏感数据,通过Vercel控制台的「环境变量」页面添加EMAIL_USER、EMAIL_PASS等变量,确保部署时能正确读取。


内容的提问来源于stack exchange,提问作者Jamal Makame

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 19:52:35