Context:
I've a NextJS deployment behind Nginx. The idea is to use NextJS to create several websites hosted in different domains. Each domain will have an entry in Nginx and it will be pointing to the specific path pages/cafes/[cafeId]
in NextJS. There will be only one NextJs deployment for all websites and each domain will be routed using static
proxy in nginx.
nginx.conf
server {
listen 80;
server_name www.cafe-one.local;
location = / {
proxy_pass http://localhost:3000/cafes/cafe_id_1;
...
}
location / {
proxy_pass http://localhost:3000/;
...
}
}
server {
listen 80;
server_name www.cafe-two.local;
location = / {
proxy_pass http://localhost:3000/cafes/cafe_id_2;
...
}
location / {
proxy_pass http://localhost:3000/;
...
}
}
pages/[cafeId]/index.js
export const getStaticPaths = async () => {
return {
paths: [], // no website rendered during build time, there are around 1000+ sites
fallback: true
};
};
export const getStaticProps = async context => {
const cafeId = context.params.cafeId;
const cafe = await ... // get data from server
return {
props: {
cafe
},
revalidate: 10 // revalidate every 10 seconds
};
};
export default function CafeWebsite(props) {
const router = useRouter();
// getStaticProps() is not finished
if (router.isFallback) {
return <div>Loading...</div>;
}
return <div>{props.cafe.name}</div>;
}
Issue:
When I access www.cafe-one.local
, i get to the loading screen, but then NextJS throw a client-side error about the The provided as value (/) is incompatible with the href value (/cafes/[cafeId])
. This is understandable because the current URL is not what NextJS is expecting.
Question:
How to fix the issue, such that NextJS could be used in front of Nginx reverse proxy?
Any help is appreciated.
Thanks in advance.
I have been dealing with the same issue, but for mapping different subdomains to a dynamic route in the NextJS app.
I haven't been able to find a proper solution to the The provided as value (/) is incompatible with the href value
error, but I found a somewhat hacky workaround.
First, you have to redirect the requests from my-domain.com
to my-domain.com/path-to-dynamic-route
. Then you have to reverse proxy all request from my-domain.com/path-to-dynamic-route
to the same dynamic route in the NextJS app, like localhost:3000/path-to-dynamic-route
.
You can do it manually from NGINX with a combination of return 301
and proxy_pass
, or you can let NextJS do it automatically by passing the dynamic route in the proxy_pass
directive with a trailing slash.
nginx.conf
server {
listen 80;
server_name www.cafe-one.local;
location = / {
# When a url to a route has a trailing slash, NextJS responds with a "308 Permanent redirect" to the path without the slash.
# In this case from /cafes/cafe_id_1/ to /cafes/cafe_id_1
proxy_pass http://localhost:3000/cafes/cafe_id_1/;
# If you also want to be able to pass parameters in the query string, you should use the variable $request_uri instead of "/"
# proxy_pass http://localhost:3000/cafes/cafe_id_1$request_uri;
...
}
location / {
# Any other request to www.cafe-one.local will keep the original route and query string
proxy_pass http://localhost:3000$request_uri;
...
}
}
This should work, but now we have a problem with the url in the address bar. Any user visiting www.cafe-one.local
will be redirected to www.cafe-one.local/cafes/cafe_id_1
and that doesn't look nice.
The only workaround I found to solve this issue was to use javascript to remove the path by rewriting the browsing history with window.history.replaceState()
.
pages/[cafeId]/index.js
...
export default function CafeWebsite(props) {
if (typeof window !== "undefined") {
window.history.replaceState(null, "", "/")
}
...
if you don't want to remove the path for all domains, you can use window.location.hostname
to check the current url.
...
export default function CafeWebsite(props) {
if (typeof window !== "undefined") {
const hostname = window.location.hostname
const regex = /^(www\.my-domain\.|my-domain\.)/
if (!regex.test(hostname)) {
window.history.replaceState(null, "", "/")
}
}
...
I've managed to handle the same issue by forcing my dynamic pages to use ONLY serverside rendering.
The fact is, Next tries to hydrate route params from the browser page URL which is outside of Next's context due to nginx.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With