Next.js env variables and building for different environments
Unanswered
Ragdoll posted this in #help-forum
RagdollOP
Hey I have a Next.js 14 app where my requirement is to just generate the app statically. Which I have working with
I have a few different enviroment files
.env.local
.env.production
.env.staging
.env.uat
I would like to run
package.json
next.config.js
Any help would be greatly appreciated.
npm run build however...I have a few different enviroment files
.env.local
.env.production
.env.staging
.env.uat
I would like to run
npm run build but for it to build production, staging and uat all separately into their own folders. I've tried a number of solutions using chat GPT and just watching YouTube but I can't seem to find anything. I know vue had a service where I have this working https://cli.vuejs.org/guide/cli-service.html but I can't seem to find the equivalent for next.jspackage.json
{
"name": "trc-nextjs-app",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"build:production": "NODE_ENV=staging next build && move .next dist_staging",
"build:staging": "NODE_ENV=staging next build && move .next dist_staging",
"build:uat": "NODE_ENV=dev next build && mv .next dist_dev",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"bootstrap": "^5.3.2",
"next": "^14.1.4",
"react": "^18",
"react-dom": "^18"
},
"devDependencies": {
"eslint": "^8",
"eslint-config-next": "14.0.1"
}
}next.config.js
module.exports = {
env: {
MY_CUSTOM_ENV_VAR: 'your_value_here'
},
output: 'export',
distDir: 'out'
};Any help would be greatly appreciated.
23 Replies
@Ragdoll Hey I have a Next.js 14 app where my requirement is to just generate the app statically. Which I have working with npm run build however...
I have a few different enviroment files
.env.local
.env.production
.env.staging
.env.uat
I would like to run
npm run build but for it to build production, staging and uat all separately into their own folders. I've tried a number of solutions using chat GPT and just watching YouTube but I can't seem to find anything. I know vue had a service where I have this working https://cli.vuejs.org/guide/cli-service.html but I can't seem to find the equivalent for next.js
package.json
{
"name": "trc-nextjs-app",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"build:production": "NODE_ENV=staging next build && move .next dist_staging",
"build:staging": "NODE_ENV=staging next build && move .next dist_staging",
"build:uat": "NODE_ENV=dev next build && mv .next dist_dev",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"bootstrap": "^5.3.2",
"next": "^14.1.4",
"react": "^18",
"react-dom": "^18"
},
"devDependencies": {
"eslint": "^8",
"eslint-config-next": "14.0.1"
}
}
next.config.js
module.exports = {
env: {
MY_CUSTOM_ENV_VAR: 'your_value_here'
},
output: 'export',
distDir: 'out'
};
Any help would be greatly appreciated.
NODE_ENV=staging is not a valid value, you really shouldn't introduce new values for this env variable because it can break libraries. I wrote about it in more details here: https://rafaelalmeidatk.com/blog/why-you-should-not-use-a-custom-value-with-node-envthe solution is to introduce your own env variable for your different environments and use that in your code to change things that depend on it
@Rafael Almeida `NODE_ENV=staging` is not a valid value, you really shouldn't introduce new values for this env variable because it can break libraries. I wrote about it in more details here: <https://rafaelalmeidatk.com/blog/why-you-should-not-use-a-custom-value-with-node-env>
the solution is to introduce your own env variable for your different environments and use that in your code to change things that depend on it
RagdollOP
how can I use npm run build to create a staging build using my staging env file?
.env.staging is not a valid file, it won't be loaded. environment variables are meant to change depending on the ENVIRONMENT, not meant to be used as configuration files. if these are just different configs for each each environment then it would be better to create a config file with json or something similar@Rafael Almeida `.env.staging` is not a valid file, it won't be loaded. environment variables are meant to change depending on the ENVIRONMENT, not meant to be used as configuration files. if these are just different configs for each each environment then it would be better to create a config file with json or something similar
RagdollOP
How do you achieve what I want to do in my intial question in Next.js?
the easiest solution is to create a .json file with multiple keys for each environment, then load it depending on the custom value or your new env var, like
APP_ENV. e.g.{
dev: { title: "Dev", color: "#fff" },
production: { title: "Production", color: "#fff" },
staging: { title: "Staging", color: "#fff" },
}the best solution is to use a .js file instead, and conditionally return a different config depending on the env variable, this allows the bundler to completely remove code from other environments:
export const getEnvConfig = () => {
if (process.env.APP_ENV === 'dev') {
return { title: "Dev", color: "#fff" }
}
if (process.env.APP_ENV === 'production') {
return { title: "Production", color: "#fff" }
}
if (process.env.APP_ENV === 'staging') {
return { title: "Staging", color: "#fff" }
}
throw new Error("Env not supported")
}RagdollOP
So how can I update my package.json file to run
npm run build:staging with the correct process.env.APP_ENV?just change the lines you are using
NODE_ENV=... to APP_ENV=... in the scripts of the package.json file@Rafael Almeida just change the lines you are using `NODE_ENV=...` to `APP_ENV=...` in the scripts of the package.json file
RagdollOP
like this
"build": "next build",
"build:production": "APP_ENV=staging next build && move .next dist_staging",
"build:staging": "APP_ENV=staging next build && move .next dist_staging",
"build:uat": "APP_ENV=dev next build && mv .next dist_dev",yes. btw I think you probably want to rename the
out folder instead of .next. give a look at your next.config.js file, you are changing the name of the output folderRagdollOP
Well my requirement is to have a build folder for production and staging, so I need to npm run build in staging mode and put that in a folder and then the same for production so that I keep both
I think I need it to copy the contents of the /out folder and then create a folder called dist_staging and dist_production or something like that
I mean you already have the commands to do what you need, but you are doing it on the wrong folder
@Rafael Almeida I mean you already have the commands to do what you need, but you are doing it on the wrong folder
RagdollOP
oh so change .next to out
@Rafael Almeida I mean you already have the commands to do what you need, but you are doing it on the wrong folder
RagdollOP
these are my scripts
when I run
I get this error
$ npm run build:staging
'APP_ENV' is not recognized as an internal or external command,
operable program or batch file.
{
"scripts": {
"dev": "next dev",
"build": "next build",
"build:production": "APP_ENV=staging next build && move out dist_staging",
"build:staging": "APP_ENV=staging next build && move out dist_staging",
"build:uat": "APP_ENV=dev next build && mv out dist_dev",
"start": "next start",
"lint": "next lint"
},when I run
npm run build:stagingI get this error
$ npm run build:staging
trc-nextjs-app@0.1.0 build:staging
APP_ENV=staging next build && move out dist_staging
'APP_ENV' is not recognized as an internal or external command,
operable program or batch file.
are you using windows? how come the previous version worked with
NODE_ENV?RagdollOP
it didn't
It was just a concept psuedo code
I am not sure what's the correct env var syntax for windows, I see most people using this: https://www.npmjs.com/package/cross-env
then the command is changed to
cross-env APP_ENV=staging next build && move out dist_staging(notice the
cross-env at the start)RagdollOP
"scripts": {
"dev": "next dev",
"build:production": "cross-env APP_ENV=production NEXT_PUBLIC_APP_ENV=production NEXT_PUBLIC_API_URL=https://evn.production-api.example.com next build && rm -rf dist_production && mv out dist_production",
"build:staging": "cross-env APP_ENV=staging NEXT_PUBLIC_APP_ENV=staging NEXT_PUBLIC_API_URL=https://evn.staging-api.example.com next build && rm -rf dist_staging && cp -r out dist_staging && rm -rf out",
"build:uat": "cross-env APP_ENV=uat NEXT_PUBLIC_APP_ENV=uat NEXT_PUBLIC_API_URL=https://evn.uat-api.example.com next build && rm -rf dist_uat && mv out dist_uat",
"start": "next start",
"lint": "next lint"
},something like this will work
@Ragdoll
"scripts": {
"dev": "next dev",
"build:production": "cross-env APP_ENV=production NEXT_PUBLIC_APP_ENV=production NEXT_PUBLIC_API_URL=https://evn.production-api.example.com next build && rm -rf dist_production && mv out dist_production",
"build:staging": "cross-env APP_ENV=staging NEXT_PUBLIC_APP_ENV=staging NEXT_PUBLIC_API_URL=https://evn.staging-api.example.com next build && rm -rf dist_staging && cp -r out dist_staging && rm -rf out",
"build:uat": "cross-env APP_ENV=uat NEXT_PUBLIC_APP_ENV=uat NEXT_PUBLIC_API_URL=https://evn.uat-api.example.com next build && rm -rf dist_uat && mv out dist_uat",
"start": "next start",
"lint": "next lint"
},
something like this will work
yeah thats fine. but if you have
NEXT_PUBLIC_APP_ENV you can remove APP_ENV because it would be redundant