Skip to content

Instantly share code, notes, and snippets.

@u8sand
Last active March 30, 2023 14:02
Show Gist options
  • Save u8sand/db56c9db4afc381c3716e9a60f96b638 to your computer and use it in GitHub Desktop.
Save u8sand/db56c9db4afc381c3716e9a60f96b638 to your computer and use it in GitHub Desktop.
This trick allows you to build nextjs projects but change the basePath at runtime

NextJS Runtime Entrypoint Reconfig

NextJS seems to have no way to reconfigure the base path (vercel/next.js#16059).

Some propose a reverse proxy, but because static pages embed the basePrefix into them this also doesn't work well.

The alternative is quite undesirable -- building at runtime.

Here, we use a hopefully unique string /__ENTRYPOINT__ as the entrypoint, this allows us to just replace this string in all the next-built files at startup when we know the actual entrypoint.

Once building with this approach, the entrypoint can be customized, this also works for images, API endpoints, and more.

Tested on next@^12 NOTE: No longer works in next@^13

Complete repo for testing this: https://github.com/u8sand/test-nextjs-runtime-entrypoint-reconfig


The assumption here is that you're building your NextJS application with Docker, these files would be put in the root of your repo and you build with

docker build -t your-tag .

then you can run with arbitrary entrypoints i.e.

docker run -p 3000:3000 -e NEXT_PUBLIC_ENTRYPOINT=/myentrypoint -it your-tag
FROM node
RUN apt-get update -y && apt-get install -y jq && rm -rf /var/lib/apt/lists/*
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . ./
RUN chmod +x ./entrypoint.sh
RUN NEXT_PUBLIC_ENTRYPOINT=/__ENTRYPOINT__ npm run build
ENV NEXT_PUBLIC_ENTRYPOINT=""
EXPOSE 3000
ENTRYPOINT ["./entrypoint.sh"]
CMD ["npm", "run", "start"]
#!/bin/sh
# replace /__ENTRYPOINT__ with the runtime-configured entrypoint
if [ "$NEXT_PUBLIC_ENTRYPOINT" = "" ]; then
# root entrypoint is handled differently from non-root, in particular
# - basePath="" rather than "/"
# - an extra redirect is added /x/ => /x -- but with root that would be // => / which is invalid
cp .next/routes-manifest.json .next/routes-manifest.json.in
jq -rc '.basePath = ""
| .redirects = [
.redirects
| .[]
| select((.source == "/__ENTRYPOINT__/" and .destination == "/__ENTRYPOINT__") | not)
]' .next/routes-manifest.json.in > .next/routes-manifest.json
fi
# first we look for /__ENTRYPOINT__/ -- this should become / in the case of empty entrypoint
# then we look for /__ENTRYPOINT__ -- this should become "" in the case of empty entrypoint
find .next \
-type f \
-exec sed -i \
-e "s#/__ENTRYPOINT__/#${NEXT_PUBLIC_ENTRYPOINT}/#g" \
-e "s#/__ENTRYPOINT__#${NEXT_PUBLIC_ENTRYPOINT}#g" \
{} +
$@
// ...
module.exports = {
// ...
basePath: process.env.NEXT_PUBLIC_ENTRYPOINT ? process.env.NEXT_PUBLIC_ENTRYPOINT : undefined,
// ...
}
@castafab
Copy link

Hi thanks for the response, but the Link one works for you? that is the case for me also the link is correct in the page href but when i click in the link, gets mangled. Also if I open in a new tab works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment