Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proxy to backend with default Next.js dev server

Before, when I made apps with create-react-app, I would have a setupProxy.js file that would route API requests similar to this

const proxy = require('http-proxy-middleware');
module.exports = function(app) {
    app.use('/api',
        proxy({
            target: 'http://localhost:8000',
            changeOrigin: true,
        })
    );
};

But that doesn't seem to work with next.js. When I do the same thing, I get various errors.

Googling a solution, a lot say to use a custom server of some kind. But how would I accomplish a proxy like above using the default nextjs dev server? (Equivalent of npm run dev when dev in my package.json is next dev.

like image 296
cclloyd Avatar asked Mar 30 '20 06:03

cclloyd


People also ask

Can I use next js for backend?

By default, Next. js includes its own server with next start . If you have an existing backend, you can still use it with Next.

Does NextJS need a server?

You don't need a node server running 24/7 for hosting your application. Also, if you don't use getServerSideProps, Next. js by default will pre-render your page, this page gets cached on a CDN. So yes you can make API calls to your PHP backend, without the need for a setting up a nodejs server yourself.

Can I use node js with next js?

One way is to build the Next. js app with NodeJS or Java and another way is to build the Next. js and serve that static content with NGINX web server. With NodeJS we have to deal with the server code as well, for example, you need to load the index.


4 Answers

There is now an official feature for this in the config: Rewrites

Besides normal path rewrites, they can also proxy requests to another webserver

next.config.js:

module.exports = {
  async rewrites() {
    return [
      {
        source: '/api/:path*',
        destination: 'http://localhost:8000/:path*' // Proxy to Backend
      }
    ]
  }
}

See Next.js Docs Rewrites

like image 158
Birkenstab Avatar answered Oct 16 '22 11:10

Birkenstab


My server.js set up, hope it helps:

import express from 'express';
import next from 'next';
import proxy from 'http-proxy-middleware';

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

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

    server.use(
        '/api',
        proxy({
            target: process.env.API_HOST,
            changeOrigin: true,
        }),
    );
 
    server.all('*', (req, res) => handle(req, res));

    server.listen(port, err => {
        if (err) throw err;
        console.log(`> Ready on http://localhost:${port}`);
    });
});

package.json:

"scripts": {
    "dev": "NODE_ENV=development node -r esm server.js",
    "build": "NODE_ENV=production next build",
    "start": "NODE_ENV=production node -r esm server.js",
},
like image 42
iamhuynq Avatar answered Oct 16 '22 10:10

iamhuynq


Rewrites didn't work for me, and neither did using axios config.proxy.

I've resorted to a good old constant:

const SERVER_URL = 
  process.env.NODE_ENV === 'production' ? 'https://produrl.com : 'http://localhost:8000';

export async function getStaticProps() {
  const data = axios.get(`${SERVER_URL}/api/my-route`)
  // ...
}

I would much rather proxy requests and keep my requests cleaner, but I don't have a day to spend wrestling with this.

Maybe this very simple setup will help others.

like image 1
alexcs Avatar answered Oct 16 '22 11:10

alexcs


Another solution with catch-all routes + http-proxy-middleware:

// pages/api/proxy/[...slug].js

import { createProxyMiddleware } from "http-proxy-middleware"; // @2.0.6

const proxy = createProxyMiddleware({
  target: process.env.BACKEND_URL,
  secure: false,
  pathRewrite: { "^/api/proxy": "" }, // remove `/api/proxy` prefix
});

export default function handler(req, res) {
  proxy(req, res, (err) => {
    if (err) {
      throw err;
    }

    throw new Error(
      `Request '${req.url}' is not proxied! We should never reach here!`
    );
  });
}

see: https://stackoverflow.com/a/72310680

like image 1
abernier Avatar answered Oct 16 '22 11:10

abernier