Getting a 404 for API routes when deploying to Heroku with Nuxt

Viewed 1451

I have no idea what is going on here. My app works just fine in development, but when I push to Heroku, it throws 404 errors whenever I try to access any routes with Postman (or with Axios). What am I doing wrong here?

Here is my index.js:

const express = require("express");
const consola = require("consola");
const { log } = console;

const { Nuxt, Builder } = require("nuxt");

const app = express();

// Import and Set Nuxt.js options
let config = require("../nuxt.config.js");

// Use routes
app.use("/api/search", require("./api/search"));

app.get("/test", (req, res) => {
    return res.send("Received");
});

config.dev = process.env.NODE_ENV !== "production";

async function start() {
    // Init Nuxt.js
    const nuxt = new Nuxt(config);

    const { host, port } = nuxt.options.server;

    const PORT = process.env.PORT || port;
    const HOST = process.env.PORT ? "myapp.heroku.com" : host;

    // Build only in dev mode
    if (config.dev) {
        const builder = new Builder(nuxt);
        await builder.build();
    } else {
        await nuxt.ready();
    }

    // Give nuxt middleware to express
    app.use(nuxt.render);

    // Listen the server
    app.listen(PORT, HOST);

    consola.ready({
        message: `Server listening on http://${HOST}:${PORT}`,
        badge: true
    });
}

process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0;

start();

And my nuxt.config.js

const pkg = require("./package");

module.exports = {
    mode: "universal",

    head: {
        title: "My app",
        meta: [
            { ...
            },
            { ...
            },
            { ...
            },
            { ...
            }
        ],
        link: [
            { ...
            },
            { ...
            },
            { ...
            }
        ],
        script: [ ...
        ]
    },

    /*
     ** Nuxt.js modules
     */
    modules: [
        [
            "@nuxtjs/axios",
            {
                baseURL: "https://myapp.herokuapp.com"
            }
        ],
        "bootstrap-vue/nuxt",
    ],

    router: {
        scrollBehavior: async (to, from, savedPosition) => {
            if (savedPosition) {
                return savedPosition;
            }

            const findEl = async (hash, x) => {
                return ( ...
                );
            };

            if (to.hash) {
                let el = await findEl(to.hash);

                if (el) { ...
                }
            }

            return { ... };
        }
    },

    /*
     ** Build configuration
     */
    build: {
        optimization: { ... 
        },
        analyze: false
    }
};

As you can see, I have a test route:

app.get("/test", (req, res) => {
    return res.send("Received");
});

Making a GET request using Postman to localhost:3000/test works fine.. but it doesnt work for myapp.herokuapp.com/test. What's going on here?

3 Answers

I don't see your server middleware settings in your nuxt.config.js file. Did you add those? If not, there's a good chance thats why it's not working. Here's a copy of part of the documentation on how to set up server middleware with nuxt.

import serveStatic from 'serve-static'

export default {
  serverMiddleware: [
    // Will register redirect-ssl npm package
    'redirect-ssl',

    // Will register file from project api directory to handle /api/* requires
    { path: '/api', handler: '~/api/index.js' },

    // We can create custom instances too
    { path: '/static2', handler: serveStatic(__dirname + '/static2') }
  ]
}

Here's a link to the nuxt server middleware docs fore more info.

I feel like because you defined the route in your express server you shouldn't need to take the above step but it couldn't hurt to try. Maybe even try moving the route into an api directory like they do in the docs. Just to make sure nuxt registers the route properly.

I'm not sure but I think nuxt might register api routes as url/api/yourRoute. Maybe try myapp.herokuapp.com/api/test. That's about all the possible issues I can think of unless there's some issue with how the project was deployed. I unfortunately have not deployed to heroku so I can't really offer any further advice.

What solved this for me was changing the command in the Procfile from nuxt start to npm run start, otherwise none of the server side code was running.

For future readers ensure that you are using server as your target

Cannot use server middleware such as express in static mode.

So your app's nuxt.config.js you can have ssr = true or false, but your target needs to be server not static. Then ensure you have wired up your serverMiddleware correctly : https://nuxtjs.org/docs/configuration-glossary/configuration-servermiddleware/

You can test that everything is working locally by running nuxt build followed by nuxt start. (Don't test that your server middleware is working with nuxt command):

 "scripts": {
    "test": "jest",
    "dev": "nuxt",
    "build": "nuxt build",
    "start": "nuxt start",
    "generate": "nuxt generate",
    "heroku-postbuild": "npm run build"
  },
Related