Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Next.js under a proxy with different path

Using next.js version 8.0.3 I don't know how to serve a custom server under a proxy with a different subpath.

I'm doing:

npm run build && npm start

In order to build and open the custom server.

And instead of open http://localhost:3000, I'm using a proxy with another subpath http://localhost:8000/example.

The proxy is simple, to reproduce it:

proxy.js

const express = require('express')
const proxy = require('http-proxy-middleware')

const options = {
  target:'http://localhost:3000/',
}
const exampleProxy = proxy(options)
const app = express()

app.use('/example', exampleProxy)
app.listen(8000)

And then:

node proxy.js

However, when I open the http://localhost:8000/example url is loading the home page but without styles, statics, javascript... Anything...

How can I do it correctly?

Thank you so much!

like image 610
Aral Roca Avatar asked Oct 17 '22 06:10

Aral Roca


1 Answers

As a caveat, I'll start by saying that I don't believe NextJS plays nice with proxies, especially on a subpath.

That being said, the following should work, with limitations :

const express = require('express')
const proxy = require('http-proxy-middleware')

const options = {
  target:'http://localhost:3000/',
  pathRewrite: {
    '^/example': ''
  }
}
const exampleProxy = proxy(options)
const app = express()

app.use(['/example', '/_next', '/static'], exampleProxy)
app.listen(8000)

The pathRewrite option makes sure /example/xyz on the proxy redirects to /xyz on your NextJS server.

You need to proxy /_next (or whatever you renamed your build directory to) so that your page finds all the built assets (scripts, stylesheets, webpack chunks, etc.). If you inspect any of your Next's project pages you'll see that these assets links are absolute, hence the need to proxy that directory as well.

You need to proxy /static for the same reason, except that directory is meant to hold your static NextJS assets (images, etc.).

You'll also notice your page links in Next are usually absolute as well (I know mine are in all my projects).

All the above is the reason why I stated that, in my opinion, NextJS isn't really suited for a subpath proxy usage.

Update:

You can add the following config in your next.config.js file at the root of your NextJS project:

module.exports = {
  assetPrefix: '/example'
}

This will prepend /example to all the built assets, so instead of /_next/pages/xyz you will link to /example/_next/pages/xyz. With this update you can remove the /_next proxy on the proxy side and your buildable assets (scripts, stylesheets, etc.) should still load.

Regarding the navigational (i.e. 'page') links within your NextJS app, as stated in my comment, you could setup your own version of Link and prepend your subpath:

import Link from 'next/link'

// for proxied server
const PROXY_PATH= '/example'
// for non-proxied server
// const PROXY_PATH= ''

export default MyLink = ({ as, children, ...props }) => <Link {...props} as={`${PROXY_PATH}${as}`}>{children}</Link>

You'd have to make sure all your MyLink components define an as prop. You don't want to change the href prop itself (the link as it is), only the as prop (the link as it appears).

Finally, for the /static assets, you'd just have to rewrite your static links inside your NextJS app, i.e. turn

<img src='/static/mylogo.svg' />

to

<img src=`${PROXY_PATH}/static/mylogo.svg` />

And the path rewrite on the proxy end should handle it correctly. With this, you could define PROXY_PATH at the project scope in a separate config file or load it from an environment variable.

like image 182
Thomas Hennes Avatar answered Nov 15 '22 06:11

Thomas Hennes