0

I am deploying a Nextjs/Express app to Vercel and am running into issues when calling /api routes. An example is this page which tries to retrieve products via redux from the server when it loads. This is working fine in dev, but I am getting a 404 error on all api routes after deploying.

index.js

const express = require('express');
const next = require('next');
const mongoose = require('mongoose');
const cookieSession = require('cookie-session');
const passport = require('passport');
const bodyParser = require('body-parser');
const keys = require('../config/keys');
require('../models/User');
require('../services/passport/passport');



const PORT = process.env.PORT || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()

mongoose.Promise = global.Promise;
mongoose.connect(keys.mongoURI, { useUnifiedTopology: true, useNewUrlParser: true, useCreateIndex: true });

app
    .prepare()
    .then(() => {
        const server = express();

        server.use(bodyParser.json({limit: '50mb'}));
        server.use(
        cookieSession({
            maxAge: 30 * 24 * 60 * 60 * 1000,
            keys: [keys.cookieKey]
        })
        );
        server.use(passport.initialize());
        server.use(passport.session());

        const getRoutes = require('./routes/index.js');
        server.use('/api', getRoutes);
        // const routes = getRoutes();

        server.get("*", (req, res) => {
            return handle(req, res);
        })

        server.listen(PORT, err => {
            if (err) throw err;
            console.log(`> Ready on ${PORT}`);
        })
    })
    .catch(ex => {
        console.error(ex.stack);
        process.exit(1);
    })

services.js

import React from 'react';
import Head from 'next/head';
import Link from 'next/link';
import Nav from '../components/Navbar/ColorNav';
import Selector from '../components/Custom/Presentation/MapSelector';
import AppointmentMobile from '../components/Custom/Presentation/Mobile-AppointmentPresentation';
import Footer from '../components/Footer/alt-footer';
import SelService from '../components/Custom/Presentation/Presentation-service.js';

const Services = () => {
    return (
        <React.Fragment>
            <div className="services-page">
            <Head>
                <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
                <link rel="preconnect" href="https://fonts.gstatic.com" />
                <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300&display=swap" rel="stylesheet"></link>
                <title>Vohnt | Services</title>
                <meta name="keywords" content="Vohnt"/>
            </Head>
            <div className="service-header">
            <Nav popBox="services"/>
            <div className="service-selector">
            <Selector />
            </div>
            {/* <div className="mobile-service-selector">
            <AppointmentMobile />
            </div> */}
            </div>
            <div className="service-section-1">
                <div className="service-sec-1-container">
                    <h2 >Vohnt’s service offerings</h2>
                    <p className="serv-1-p">Creating a world where you have immediate, convenient, and affordable access to car care.</p>
                    <div className="serv-1-button">
                    <Link href="/how-it-works">
                    <button className="learn-more-button" id="no-border-radius">Learn More</button>
                    </Link>
                    </div>
                </div>
                <div className="vohnt-product-offerings">
                    <div className="product-list-left">
                        <SelService simpleHeight='600px' buttons="services"/>
                    </div>
                    <div className="product-list-left-small">
                        <SelService simpleHeight='420px' buttons="services"/>
                    </div>
                    <div className="product-list-left-small2">
                        <SelService simpleHeight='400px' buttons="services"/>
                    </div>
                    <div className="product-list-left-small3">
                        <SelService simpleHeight='350px' buttons="services"/>
                    </div>
                </div>
            </div>
            <div className="alt-footer-2">
            <Footer />
            </div>
            </div>
        </React.Fragment>
    )
}

export default Services;

presentation-service tells redux to call on page load

    useEffect(() => {
        dispatch(loadProducts());
    }, [])

2 Answers 2

0

You cannot host a Next/express app on Vercel because the Express server must be running all the time, but Vercel is made for serverless functions.

Two possible solutions:

  1. Host your app in Heroku or a vps
  2. Remove Express, just use Next api routes and you will easily deploy on Vercel

Reference

Sign up to request clarification or add additional context in comments.

2 Comments

Didn't realize vercel was completely serverless, thanks! was able to deploy no problem on heroku and am researching now if it is worth the effort to switch from express to nextjs api.
why does this work for the browser but not from my app?
0

Here is the official Using Express.js with Vercel article.

We recommend using API Routes with Next.js to create Serverless Functions.

Any file inside the folder pages/api is mapped to /api/* and will be treated as an API endpoint instead of a page.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.