Reputation: 221
Noob question, my apologies.
I'm wondering if anyone knows the recommended deployment flow for NextJS self-hosted (e.g. docker or kubernetes). I'm doing a typical build once, ship per environment while changing environment variables to match the environment but keeping the image the same.
Since NextJS auto-opts-out of SSG when you use "getInitialProps" and "publicRuntimeConfig", I'm wondering, what's the best way to deploy the same image to multiple environments (again, self hosted on generic cloud e.g. docker run).
Thanks for your help!
Upvotes: 20
Views: 13126
Reputation: 511
Don't bake your environment variables into the build, if you want to deploy the same build everywhere. Also, client side environment variables must be baked in at the build time in Next.js. So what to do? The answer is runtime environment variables
To read runtime environment variables, we recommend using getServerSideProps or incrementally adopting the App Router.
This is the recommended technique by Next.js docs for Build Once Deploy Anywhere.
Upvotes: -1
Reputation: 41
I've implemented lib that does everything including hot ENV reloading, etc. Works like a charm and we started to use it to simplify CI/CD and secrets storage for our projects.
https://www.npmjs.com/package/@cuww/runtime-env
Upvotes: 2
Reputation: 1447
A not optimal solution is to build the Next project at runtime of your container, that way you will be able to read environment variables at runtime.
This has (at least) two obvious downsides:
Example of Dockerfile
with build at runtime:
FROM node:18-alpine
WORKDIR /app
ENV NODE_ENV production
ENV NEXT_TELEMETRY_DISABLED 1
COPY ./public public
COPY ./src src
COPY .env.local .env.local
COPY next.config.js next.config.js
COPY package.json package.json
COPY tsconfig.json tsconfig.json
COPY node_modules node_modules
# Create and give access to folders and files that will be edited during build time
RUN mkdir -p .next
RUN touch next-env.d.ts
RUN chmod -R ugo+rwX .next next-env.d.ts
USER 1001
EXPOSE 8080
ENV PORT=8080
ENTRYPOINT ["/bin/sh", "-c", "npm run build && npm run start"]
Upvotes: -2
Reputation: 379
I will expand on @gyum-fox answer, because react-env
docs wasn't up to date and couple of things took some time to figure out.
Next.js version: 12.2.5
In react-env
Next.js repo were used 2 packages: react-env
and @beam-australia/react-env
. I don't know what's the purpose of the former, I used the latter.
react-env
claims it's isomorphic, but I can't manage to make it work server side. So here comes the changes to .env file
REGULAR_VAR=VALUE
NEXT_PUBLIC_REGULAR_VAR=$REGULAR_VAR
Some variables I used both on server and client, so to make it work:
REGULAR_VAR
was used on server, manages in .env
fileNEXT_PUBLIC_REGULAR_VAR
was used on client like this: env('REGULAR_VAR')
(note: NEXT_PUBLIC
prefix was removed). Manages in __ENV.js
fileTo use __ENV.js
file in Next.js, place the following line in _document.tsx
<Script src="/__ENV.js" strategy="beforeInteractive" />
Note: while __ENV.js
sits in /public
directory, at run-time file will be in root, as every file of that directory will be
__ENV.js
filereact-env
command only needed to generate __ENV.js
, so you can launch project:
# like this
npx react-env --prefix NEXT_PUBLIC -- node server.js
# or like this
yarn react-env --prefix NEXT_PUBLIC && node server.js
--prefix NEXT_PUBLIC
: NEXT_PUBLIC
is the default for client side env varsnode server.js
: or next dev
or any other command to launch the projectI use Dockerfile from Vercel example for deployment.
To generate __ENV.js
file in container, change
RUN yarn build
to
RUN npx react-env --prefix NEXT_PUBLIC --path .env.production -- yarn build
Here, I added --path .env.production
to use production env vars.
That's it! Now you can change client env vars in __ENV.js
, restart the
production server and new values will be applied.
Upvotes: 2
Reputation: 3627
You might want to check out react-env which does just that.
The idea is that react-env will generate for you an __ENV.js
JS file with your environment variables, which you can then access on client side via the window or via the env
helper, eg:
<small>
Works in the browser: <b>{env("CRA")}</b>.
</small>
When using Docker, you may set an entrypoint that generates the required __ENV.js
when the container boots:
ENTRYPOINT yarn react-env --env APP_ENV
Upvotes: 3