mongodbnext.jshostingvercel

In hosting Next.js app to Vercel, backend API is not working


I've hosted Next.js app to vercel using GitHub. Before deploying the app, I set environment variables from .env file. Here I used custom server.js file to start server. I used node server.js script to start server, not using next start.

In package.json file

"scripts": {
    "start": "node server",
    "dev": "next dev",
    "build": "next build",
    "serve": "next start",
    "lint": "next lint"
  }

server.js file

const express = require('express');
const https = require('https');
const fs = require('fs');
const next = require('next');
const dotenv = require("dotenv");
const morgan = require("morgan");
const bodyParser = require('body-parser');
const cors = require("cors");
const path = require('path');
const connectToMongodb = require('./src/db/mongodb');
dotenv.config({ path: "./.env" });
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
console.log('started')
app.prepare().then(() => {
  const server = express();
  server.use(morgan('dev'))
  server.use(express.json());
  server.use(cors());
  server.use(bodyParser.json());
  server.use(express.static(path.join(__dirname, 'public')))
  const options = {
    key: fs.readFileSync('key.pem'),
    cert: fs.readFileSync('cert.pem')
  };
  console.error('before connecting...')
  connectToMongodb();
  console.error('after connecting...')
  console.log('after connecting...')
  server.all('*', (req, res) => {
    return handle(req, res);
  });
  https.createServer(options, server).listen(443, () => {
    console.log('Server running on https://localhost');
  });
});

I think there is no need to create https server when deploying to vercel.

After deploying and starting server, frontend part works fine, but it seems that backend is not working. And Vercel Serverless Function can not handle of incoming API requests, I think.

How can I fix this and make backend works fine?


Solution

  • Since you are using Next.js, there is no need to create a separate express server for your backend.

    If you are using Next.js v12 (or lower), or using the pages router, you can use API routes.

    Any file inside the folder pages/api is mapped to /api/* and will be treated as an API endpoint instead of a page. They are server-side only bundles and won't increase your client-side bundle size.

    https://nextjs.org/docs/pages/building-your-application/routing/api-routes

    That means, if you want to create an api: api/hello, create a file called pages/api/hello.js, with below contents:

    import connectToMongodb from './src/db/mongodb';
    
    export default function handler(req, res) {
      connectToMongodb()
    
      res.status(200).json({ message: 'Hello from Next.js!' })
    }
    

    If you are using Next.js 13 (or later) and using app router, you can use Route Handlers.

    Route Handlers allow you to create custom request handlers for a given route using the Web Request and Response APIs.

    https://nextjs.org/docs/app/building-your-application/routing/route-handlers

    You need to create the file: app/api/hello/route.js instead, with the below contents:

    import { NextResponse } from 'next/server'
    
    export async function GET(request) {
      return NextResponse.json({ message: 'Hello from Next.js!' })
    }