1
votes

I am new to express and next and was trying to set 'localhost:3000/newpage' and 'localhost:3000/newpage/' as the same route however as I add a '/' at the end it shows a 404 error.

I am using "next-routes" for dynamic routing and have created routes.js file that looks like this:

const nextRoutes = require("next-routes");
const routes = (module.exports = nextRoutes());

routes.add("index", "/");
routes.add("newpage", "/newpage/:slug"); //with body parser this doesnt work

and my server.js file looks like this:

const express = require("express");
const next = require("next");
const routes = require("./routes");
const dev = process.env.NODE_ENV !== "production";
const port = process.env.PORT || 3000;
const app = next({ dev });
const handle = app.getRequestHandler();
const bodyParser = require("body-parser");
const handler = routes.getRequestHandler(app);
app
  .prepare()
  .then(() => {
    const server = express();
    server.use(bodyParser.json()); //with this dynamic routes dont work
    server.use (handler); //with this dynamic routes work but / url show 404

    server.get("*", (req, res) => {
      server.use(handler);
      if (req.url.endsWith("/")) {
        req.url = req.url.slice(0, -1); // works only when using body parser
      }
      return handle(req, res);
    });

    server.listen(port, (err) => {
      if (err) throw err;
      console.log("> Ready on http://localhost:3000");
    });
  })
  .catch((ex) => {
    console.error(ex.stack);
    process.exit(1);
  });



2

2 Answers

1
votes

You can modify the url that you get before passing it to Next's handling.

const next = require('next');
const express = require('express');
const routes = require('./routes');
const port = process.env.PORT || 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({dev});
const handle = app.getRequestHandler();
// const handler = routes.getRequestHandler(app); // redundant line

app.prepare().then(() => {
  const server = express();
  // server.use(handler); // <-- this line is redundant since you need only one handle!
  server.get('*', (req, res) => {
    if (req.url.endsWith('/')) {
      req.url = req.url.slice(0, -1); // remove the last slash
    }
    return handle(req, res);
  });
  server.listen(port, (err) => {
    if (err) throw err;
    console.log('> Ready on http://localhost:3000');
  });
});

Working example: https://codesandbox.io/s/express-nextjs-react-c47y8?file=/src/index.js

Navigate to /form or /form/

0
votes

I had to install the body-parser package then used body-parser. I also changed the folder structure such that I didn't have to import the routes. The final code in server.js looks like this:

const express = require("express");
const next = require("next");

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

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

    server.get("*", (req, res) => {
      if (req.url.endsWith("/")) {
        req.url = req.url.slice(0, -1); // remove the last slash
      }

      return handle(req, res);
    });

    server.listen(port, (err) => {
      if (err) throw err;
      console.log("> Ready on http://localhost:3000");
    });
  })
  .catch((ex) => {
    console.error(ex.stack);
    process.exit(1);
  });