Reputation: 103
I am working in a Next.js app, and I've create an api route to send emails.
Everthing is working in my development environment.
However, when I deployed to production I just receive a 404
- The page could not be found
error as response for this api route.
I am not the creator of the project, I suspect the problem is in the npm command used to deploy.
I just created a file in 'pages/api' and include this: server.post('*', (req, res) => handle(req, res));
on the server.js file. Do I need to do anything else?
I am using Vercel to deploy.
These are my scripts in the package.json
file:
"scripts": {
"dev": "node index.js",
"build": "NODE_ENV=production next build",
"start": "node index.js",
"export": "next export",
"now-build": "next build && next export -o dist"
}
In local environment I am using npm start
command.
My build command in production is npm run now-build
This is the index.js
file:
const { setConfig } = require('next/config')
setConfig(require('./next.config'))
require('./server')
This is the server.js
file:
const express = require('express');
const next = require('next');
const nextI18NextMiddleware = require('next-i18next/middleware').default;
const nextI18next = require('./i18n');
const port = process.env.PORT || 3007;
const app = next({ dev: process.env.NODE_ENV !== 'production' });
const handle = app.getRequestHandler();
(async () => {
await app.prepare();
const server = express();
server.post('*', (req, res) => handle(req, res));
server.use(nextI18NextMiddleware(nextI18next));
server.get('*', (req, res) => handle(req, res));
await server.listen(port);
console.log(`> Ready on http://localhost:${port}`); // eslint-disable-line no-console
})();
This is my api route file in pages/api/send-email.js
:
import sendEmail from '../../utils/sendEmail';
export default async (req, res) => {
if (req.method === 'POST') {
const { to, subject, html } = req.body;
const response = await sendEmail({ to, subject, html });
if (response.success) {
return res.status(200).end();
}
return res.status(500).json(response);
}
return res.status(400).end();
};
This is how I am calling the api route:
fetch('/api/send-email', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
to: formEmailTo,
subject: formEmailSubject,
html: FormEmailContent
})
})
.then((response) => {
if (!response.ok) {
throw Error(response.statusText);
}
return response;
})
.then(() => handleOpenSnackbarMsg())
.catch(() => handleOpenSnackbarErrMsg());
This is my next.config.js
file:
const withCSS = require('@zeit/next-css')
const withImages = require('next-images');
module.exports = withImages(
withCSS({
exportTrailingSlash: true,
exportPathMap: function() {
return {
'/': { page: '/' },
'/blank-page': { page: '/blank-page' },
};
},
publicRuntimeConfig: {
localeSubpaths: typeof process.env.LOCALE_SUBPATHS === 'string'
? process.env.LOCALE_SUBPATHS
: 'none',
},
webpack: (config, options) => {
cssModules: true,
// config.module.rules.push({
// enforce: 'pre',
// test: /\.js?$/,
// exclude: [/node_modules/],
// loader: 'eslint-loader',
// options: {
// quiet: true,
// }
// });
config.node = {
fs: 'empty'
}
return config;
},
})
);
Thank you!
Upvotes: 7
Views: 14437
Reputation: 715
I think your problem was your framework preset which was set to "Other".
It should be "Next.js".
Upvotes: 0
Reputation: 68
Vercel does not support custom servers! You have to host it on a vps.
Upvotes: 1
Reputation: 31
You cannot use next export if your project contains API routes. Remove next export
from "now-build": "next build && next export -o dist"
.
Reference: https://nextjs.org/docs/api-routes/introduction#caveats
Upvotes: 3