Vercel部署Express+Nodemailer邮件API时Serverless函数崩溃问题
我在Vercel部署一个仅处理邮件API的Express后端应用,用Nodemailer实现邮件发送功能,但部署后Serverless函数崩溃,报错提示require is not defined in ES module scope。
我的package.json

我的server.js代码
import express from "express"; import cors from "cors"; import bodyParser from "body-parser"; import nodemailer from 'nodemailer'; import { config } from "dotenv"; config() const app = express(); app.use(bodyParser.json({ limit: "100mb" })); app.use(bodyParser.urlencoded({ limit: "100mb", extended: true })); app.use(cors({credentials:true})); const transporter = nodemailer.createTransport({ service: 'gmail', auth: { user: process.env.EMAIL_USER, // 使用环境变量而非硬编码 pass: process.env.EMAIL_PASSWORD, // 使用环境变量而非硬编码 } }); function sendEmail(req, res) { const { name, email, message } = req.body; const mailOptions = { from: process.env.EMAIL_USER, to: process.env.RECIEVER_MAIL, subject: `You got a message from ${name}`, html: `<h4>Hello, Someone Contacted you through contact Form</h4> <h4>Name: ${name}</h4> <h4>Email: ${email}</h4> <p>Message: ${message}</p> ` , }; transporter.sendMail(mailOptions, function (error, info) { if (error) { console.log(error); res.status(500).json({code:500, error: 'Failed to send email' }); } else { console.log('Email sent: ' + info.response); res.status(200).json({code:200,success: 'Email sent successfully' }); } }); } app.get('/', (req, res)=>{ res.send("This is my api running!") }) app.post('/contact', (req, res) => { sendEmail(req, res); }); const PORT = process.env.PORT || 5000; app.listen(process.env.PORT,()=>{ console.log(`App listening on port ${PORT}`) })
我的vercel.json配置
{ "version": 2, "builds": [ { "src": "server.js", "use": "@now/node" } ], "routes": [ { "src": "/(.*)", "dest": "server.js" } ] }
报错日志
Uncaught Exception {"errorType":"ReferenceError","errorMessage":"require is not defined in ES module scope, you can use import instead\nThis file is being treated as an ES module because it has a '.js' file extension and '/var/task/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.","stack":["ReferenceError: require is not defined in ES module scope, you can use import instead","This file is being treated as an ES module because it has a '.js' file extension and '/var/task/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension."," at file:///var/task/___now_launcher.js:1:18"," at ModuleJob.run (node:internal/modules/esm/module_job:194:25)"]}
Uncaught Exception {"errorType":"ReferenceError","errorMessage":"require is not defined in ES module scope, you can use import instead\nThis file is being treated as an ES module because it has a '.js' file extension and '/var/task/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.","stack":["ReferenceError: require is not defined in ES module scope, you can use import instead","This file is being treated as an ES module because it has a '.js' file extension and '/var/task/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension."," at file:///var/task/___now_launcher.js:1:18"," at ModuleJob.run (node:internal/modules/esm/module_job:194:25)"]}
Unknown application error occurred
Runtime.Unknown
解决办法
原因分析
报错核心是:项目package.json中设置了"type": "module",所有.js文件被当作ES模块处理,但Vercel旧版构建器@now/node(已弃用)内部使用CommonJS的require语法,与ES模块环境冲突,导致启动器崩溃。
修复步骤
替换Vercel构建器
将vercel.json里的@now/node替换为官方推荐的@vercel/node(支持ES模块):{ "version": 2, "builds": [ { "src": "server.js", "use": "@vercel/node" } ], "routes": [ { "src": "/(.*)", "dest": "server.js" } ] }适配Serverless环境的启动逻辑
Vercel Serverless函数不需要调用app.listen(),需导出Express实例供平台调用,修改server.js最后部分:// 移除原有listen代码 // const PORT = process.env.PORT || 5000; // app.listen(process.env.PORT,()=>{ // console.log(`App listening on port ${PORT}`) // }) // 导出Express实例 export default app;确认环境变量配置
在Vercel项目的「Settings」→「Environment Variables」中,正确配置EMAIL_USER、EMAIL_PASSWORD、RECIEVER_MAIL三个变量,确保部署时能正常读取。验证Gmail权限(可选)
若使用Gmail发送邮件,需开启「不太安全的应用访问」(或为开启2FA的账号生成App密码),否则会被Google拦截。
完成以上步骤后重新部署,即可解决问题。
内容的提问来源于stack exchange,提问作者Lokesh

