deploy next.js + express to vercel
Answered
Lapland Longspur posted this in #help-forum
Lapland LongspurOP
I have already deployed my front end (using app router) website to vercel and now I'm creating an email functionality. I used express and deployed my api to cyclic. Everything works fine, however I've read some articles that vercel supports deployment of express app or convert it to serverless functions which prompted me to migrate my api into vercel. I've tried putting my api
send-email.js to /api/. Either way I ran into some errors. Any help is much appreciated.Answered by tafutada777
i found the similar issue as yours in SO.
https://stackoverflow.com/a/65634795/5850539
https://stackoverflow.com/a/65634795/5850539
18 Replies
although the Vercel official documents say it is possible, but the officail docs also say it is not recommended. plz take a look at this.
https://vercel.com/guides/using-express-with-vercel#re-thinking-our-application
https://vercel.com/guides/using-express-with-vercel#re-thinking-our-application
Vercel magic is designed for serverless environments like AWS Lambda and Cloudflare Worker. but express cannot leverage the Vercel magic though.
@tafutada777 although the Vercel official documents say it is possible, but the officail docs also say it is not recommended. plz take a look at this.
https://vercel.com/guides/using-express-with-vercel#re-thinking-our-application
Lapland LongspurOP
Is there any way to convert my express code into serverless function?
if it a handfull codes, you can migrate them without using Express, otherwise you want to stick with self-hosted env.
@tafutada777 if it a handfull codes, you can migrate them without using Express, otherwise you want to stick with self-hosted env.
Lapland LongspurOP
Here's my code:
const express = require("express")
const bodyParser = require("body-parser")
const nodemailer = require("nodemailer")
const cors = require("cors")
require("dotenv").config()
const app = express().use(bodyParser.json())
const corsOptions = {
origin: '*',
credentials: true,
optionSuccessStatus: 200,
}
app.use(cors(corsOptions))
const myEmail = process.env.EMAIL
const password = process.env.PASSWORD
app.post("/", (req, res) => {
try {
const { name, email, message } = req.body
const transporter = nodemailer.createTransport({
service: "gmail",
auth: {
user: myEmail,
pass: password
},
host: "smtp.gmail.com",
port: 465,
secure: true,
})
const mailOptions = {
from: myEmail,
to: myEmail,
subject: "Portfolio Email",
text: `Name: ${name}\n\nEmail: ${email}\n\nMessage: ${message}`,
}
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
console.error(error)
res.status(500).json({ error: "Failed to send email" })
} else {
console.log("Email sent:", info.response)
res.status(200).json({ message: "Email sent successfully" })
}
})
} catch (error) {
console.log(error)
}
}).listen(process.env.PORT || 4000, () => {
console.log(`Server is running on port ${process.env.PORT || 4000}`)
})Is it possible?
technically it is possible but some caveat. AWS lambada has wall clock time cap 10 seconds, so if the sendMail server takes 11 seconds it fails.
if there is asycn version of sendMail, you can deploy it to Edge Runtime, where it is measured by CPU time 50ms instead of wall clock time. meaning it runs longer than 10 sec. but you can not use 'require', use 'import'
@tafutada777 if there is asycn version of sendMail, you can deploy it to Edge Runtime, where it is measured by CPU time 50ms instead of wall clock time. meaning it runs longer than 10 sec. but you can not use 'require', use 'import'
Lapland LongspurOP
so all i need to do is add
"type": "module" and add async to my function?im not sure. you want to try it to see how it works as it is really small piece of code.
just keep in mind that Vercel has two runtimes: Serverless(AWS Lambada) and Edge(Cloudflare Worker)
the former is a Node.js, while the other is a subset of Node.js named V8 Isolates.
so some of libraries like axios does not work in Edge.
just keep in mind that Vercel has two runtimes: Serverless(AWS Lambada) and Edge(Cloudflare Worker)
the former is a Node.js, while the other is a subset of Node.js named V8 Isolates.
so some of libraries like axios does not work in Edge.
@tafutada777 im not sure. you want to try it to see how it works as it is really small piece of code.
just keep in mind that Vercel has two runtimes: Serverless(AWS Lambada) and Edge(Cloudflare Worker)
the former is a Node.js, while the other is a subset of Node.js named V8 Isolates.
so some of libraries like axios does not work in Edge.
Lapland LongspurOP
Okay. Thanks!
Last question, I should remove the
Last question, I should remove the
.listen in production right?yes
even in dev. don't run a server from Next.js framework. its a framework. Vercel takes care of it.
@tafutada777 even in dev. don't run a server from Next.js framework. its a framework. Vercel takes care of it.
Lapland LongspurOP
So what endpoint should I post here when using serverless function?
axios.post("https://stormy-onesies.cyclic.cloud", {
name: values.name,
email: values.email,
message: values.message
})go through the official docs about api
https://nextjs.org/docs/app/building-your-application/routing/route-handlers
https://nextjs.org/docs/app/building-your-application/routing/route-handlers
Lapland LongspurOP
@tafutada777 hello, I've made serverless function to work in my project but only in dev. When I deploy it in prod and tried sending email, it says email sent successfully but I didn't receive it in my gmail. However, when I'm running localhost with my app and tried sending email, i can receive the message perfectly fine in my gmail. I have set up my local env variables already in vercel and called it using
process.env . Also, when I check the console when sending in prod, it says email sent successfully but again I didn't receive the message in my gmail. Do I still need to do additional steps to deploy serverless function in prod?i found the similar issue as yours in SO.
https://stackoverflow.com/a/65634795/5850539
https://stackoverflow.com/a/65634795/5850539
Answer
@tafutada777 i found the similar issue as yours in SO.
https://stackoverflow.com/a/65634795/5850539
Lapland LongspurOP
broo thank you so much! all I need is just add await for the
sendMail method