NextJS - How to get runtime environment variables
Asked Answered
C

5

20

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).

  1. Do I have to always bake in the environment variables? So I have to build an image per environment, and per update to env vars.
  2. Use publicRuntimeConfig / getInitialProps but forget about SSG optimisation, even if my variables are non-sensitive (e.g. GA_TRACKING_ID)
  3. ... Is there anything else?

Thanks for your help!

Coulomb answered 31/12, 2020 at 12:46 Comment(1)
I'm wondering about the same too. Maybe is worth to try dotenv in next.config.jsSchutt
L
3

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
Limousin answered 2/9, 2021 at 9:22 Comment(3)
what about server side-only variables?Gnash
you might want to check the answer from @iamkirill https://mcmap.net/q/626587/-nextjs-how-to-get-runtime-environment-variablesLimousin
I also came accross import-met-env recently, which seems to achieve the same purpose and also works on server side. I haven't tried yet. but you should have a look.Limousin
F
2

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

Packages

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.

"Isomorphic"

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 file
  • NEXT_PUBLIC_REGULAR_VAR was used on client like this: env('REGULAR_VAR') (note: NEXT_PUBLIC prefix was removed). Manages in __ENV.js file

Using the package

To 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

Generating __ENV.js file

react-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 vars
  • node server.js: or next dev or any other command to launch the project

Docker

I 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.

Conclusion

That's it! Now you can change client env vars in __ENV.js, restart the production server and new values will be applied.

Foregoing answered 29/10, 2022 at 14:28 Comment(1)
Alternative to @beam-australia/react-env: github.com/expatfile/next-runtime-env (similar approach)Ritchey
S
2

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

Sclerometer answered 25/7, 2023 at 15:55 Comment(0)
R
-1

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.

Ratcliffe answered 27/5 at 13:46 Comment(0)
R
-2

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:

  • slower startup
  • larger image size

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"]
Ritchey answered 14/5, 2023 at 11:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.