Using Environment Variables in nuxt.config.js - node.js

I'm using Nuxt & Axios but having trouble using environment variables when building the application from my local machine.
I have installed the #nuxtjs/dotenv module in an attempt to fix this issue but still having problems.
Note: The environment variables work fine when building the app within my hosting providers environment. It is only building from my local machine that gives me trouble. My IDE is VS Code.
Here is my axios setup inside nuxt.config.js:
module.exports = {
...
buildModules: [
'#nuxtjs/dotenv'
],
modules: [
// Doc: https://axios.nuxtjs.org/usage
'#nuxtjs/axios'
],
axios: {
baseURL: process.env.BASE_URL
},
...
}
My .env file has the following:
BASE_URL="https://some.api.com"
The .env variables are not being recognized when building the app:
nuxt build
Instead, it just sets the axios base url to the same host:port that the server runs on by default. Ex: localhost:4000
I found the following documentation from #nuxtjs/dotenv module: https://github.com/nuxt-community/dotenv-module#using-env-file-in-nuxtconfigjs. This instructs you to add the following to the top of nuxt.config.js:
require('dotenv').config()
This works for building locally; my variables from .env are recognized! However, because dotenv is a dev dependency, this causes the build to crash when deployed to my hosting provider because the module isn't recognized.
I know that I can define the environment variables directly in the build command as follows but I would prefer NOT to do so:
NUXT_ENV_BASE_URL=some.api.com nuxt build
Is there an easy way to get environment variables to work locally inside of nuxt.config.js during the build process that also works well when deploying to production??
Thank you!

Updated 2020-09-26
As of 2.13.0 I have removed #nuxtjs/dotenv. My nuxt.config.js now simply reads as below with the dotenv imports removed. I made no other code changes and the rest functions exactly the same for me.
env: {
DB_HOST: process.env.DB_HOST
},
My .env contains the following.
DB_HOST=http://localhost:5001/
Original answer
I installed the following as a dev dependency; #nuxtjs/dotenv. Then I added the following to my nuxt.config.js. I found this import statement in an article and tried it. Thankfully it worked for me.
import dotenv from "dotenv";
dotenv.config();
env: {
DB_HOST: process.env.DB_HOST
},
I created a file called .env with the following content
DB_HOST=http://localhost:5001/

In nuxt version v2.13.0, support for Runtime Config was added. This adds proper support to read environment variables at runtime. Previously they could be read but were compiled into the application.
The standard documentation is pretty good: https://nuxtjs.org/guide/runtime-config/ .
There is also a great blog post on how to migrate. You remove the use of #nuxtjs/dotenv.
https://nuxtjs.org/blog/moving-from-nuxtjs-dotenv-to-runtime-config/
For example, in your nuxt.config.js, you define.
// Public env variables that are exposed on the frontend.
publicRuntimeConfig: {
someAccessKeyId: process.env.SOME_ACCESS_KEY_ID,
},
// Private env variables that are not be exposed on the frontend.
privateRuntimeConfig: {},
Then in your vue code, you access it via.
const { someAccessKeyId } = this.$config

Related

.env variables not available in jest testing environment

When I run my code normally I can access my .env file with const newVar = process.env.MY_DOTENV_VARIABLE, but when I run jest everything becomes undefined. Is this normal for jest? If so, what is the best practice for storing variables?
Is it simply to create a set up file, eg:
// jest.config.ts
setupFiles: [
"<rootDir>/.jest/setEnvVars.ts",
],
# .env
MY_DOTENV_VARIABLE=exampleString
I just needed to install dotenv. I think I got confused where process.env was working previously without the dotenv packaging. This was either due to me setting the env variables with scripts in my package.json file, eg "scripts":"NODE_ENV=test ..." and/or some packages were making changes. (I'm using various aws packages, and I've read that they can change environment variables)

process.env.NODE_ENV always 'development' when building nestjs app with nrwl nx

My NX application's npm run build:server calls ng build api-server that triggers the #nrwl/node:build builder.
It builds the NestJS application as main.js. Things work except I wanted process.env.NODE_ENV to be evaluated at runtime but I think it was resolved at build time (via Webpack).
Currently, the value is always set to 'development'.
I am new to Nrwl's NX. Any solution this?
In NestJs/Nodejs app in Nx.Dev workspace process.env.NODE_ENV is replaced during compilation from typescript to javascript very "smart way" to "development" string constant (everything like NODE_ENV is replaced). I don't know why. But only way how can I get real NODE_ENV in runtime is this code:
//process.env.NODE_ENV
process.env['NODE' + '_ENV']
The reason you're seeing development is because you're building the app in development mode - it's not best practice to evaluate at runtime because then the builder can't do fancy things to make the build production ready. If you want production, you need to build the app in production mode by adding the --prod flag (just like how you need to build Angular in production mode).
If you need to serve the app in production mode (instead of build) the default config doesn't provide you with a prod mode for serve. You'll need to add the configuration to your angular.json.
So this code:
"serve": {
"builder": "#nrwl/node:execute",
"options": {
"buildTarget": "api-server:build"
}
},
Would become
"serve": {
"builder": "#nrwl/node:execute",
"options": {
"buildTarget": "api-server:build"
},
"configurations": {
"production": {
"buildTarget": "api-server:build:production"
}
}
},
and then you can run
ng serve --project=api-server --prod
Indeed the nx builder will replace the expression process.env.NODE_ENV in our source code with the current value of the env var (or the nx-mode).
What happens is this:
the build command executes the nx builder which creates a configuration for web-pack
this configuration instructions for the webpack-define plugin to replace the text process.env.NODE_ENV during compilation with the actual value of the env-var (or the nx-mode):
see nx-code getClientEnvironment()
Since the webpack-define plugin will look for the text process.env.NODE_ENV, it's easy to use a workaround as explained in this answer:
process.env['NODE'+'_ENV']
Warning
When you need to apply this workaround to make your app work, then something is wrong. Since you have compiled your app in production mode, it does not make sense to pass another value for NODE_ENV when you start the (production) app.
The webpack Production page contains some helpful info.
We also had this case, and the issue was, that we relied on the NODE_ENV variable to load different database configs for dev, prod, test, etc.
The solution for our case was to simply use separate env-vars for the database config (e.g. DB_NAME, DB_PORT, ..), so that we can use different db-configs at runtime with any build-variants: dev, prod, test, etc.
I recently faced the same problem using Express instead of Nest.
What we did to overcome this was adding some file replacements when compiling for any of our environments (development, production, staging, staging-dev). This is done in the angular.json file the same way the environment files are replaced for the Angular app .
Another approach that worked for us, was loading the environment variables only once, and retrieve them from that origin. As our app relies on Express for it's backend the used the Express env variable as:
import express from 'express';
const _app = express();
const _env = _app.get('env');
console.log(_env); // shows the right environment value set on NODE_ENV
To come to this conclusion we checked Express code for the env variable and it does use process.env.NODE_ENV internally.
Hope it helps. Best regards.
We had the same issue, we eventually used the cross-env package in our package.json:
"prodBuild": "cross-env NODE_ENV=production nx run api-server:build:production",
"prodServe": "cross-env NODE_ENV=production nx run api-server:serve:production"
process.env is indeed only available at run-time. What is probably happening is that you are not setting this value when running your application. Can I ask how you are running it?
As a trivial example
# The following will read the environment variables that are defined in your shell (run `printenv` to see what those are)
> node main.js
# this will have your variable set
> NODE_ENV=production node main.js
Of course you want to have it actually set in your environment when deploying the app rather then passing it in this way, but if you're doing it locally you can do it like this.

Using dotenv with bundled client side code

I am creating a node js application as a Contentful UI Extension. The code is hosted here: https://github.com/doodybrains/media-tagging-extension
A lot of the gulp file is boiler plate but in the end everything gets bundled into an index.html file. I know that env variables shouldn't be called or processed in the client code but I don't know how to get them in there before the project is built. When I run the repo in development and call process.env.NAME_OF_TOKEN from src/index.js it returns undefined. I have tried import dotenv, creating a gulp env pipeline etc.
ANY ADVICE will be so helpful. The app is being deployed to Netlify and I already have the env variables set up there as well.
thank you
You can create another js file which can use NODE_ENV to set correct variable.
I prefer calling a service to get all my properties on app start and set in some map. I use the map to set the value in different places in my code.
Some sample code...
const env = process.env.NODE_ENV || 'local';
const sit = {
URL: 'sit url',
HOST: 'sit host',
ENV: 'sit'
};
const uat = {
URL: 'uat url',
HOST: 'uat host',
ENV: 'uat'
};
var property_service_url = config[env].URL;
var property_service_host = config[env].HOST;
Before starting your app, you can set the NODE_ENV=environment. For example in linux.
export NODE_ENV=uat
This will make sure that environment set correctly. Now in your app.js for , you can call the service to load your properties. If you don't want to call a service, you can set it in the same way the URL and HOST are set.

Using environment variables in Node

I have been trying to get a streamline way of having different environment variables for local and production web apps, but I haven't come across the "ideal" solution yet.
There's the option of having a config.js file like so:
//config.js
{
"secretKey": "SDFDASFFSFD",
"facebook": {
"clientID": "EFGFDGBGDGFS",
"clientSecret": "EGDFNHFG"
}
}
And accessing via ES6 imports
Or using .env files like so:
SOME_KEY=someValue
HELLO=world
FACEBOOK_SECRET=435SDFSF5DZVD7S
And accessing the variables via process.env in the code using dotenv.
Obviously no matter what route you go down, the file will need to be omitted from version control which is fine. Each of these ways are great, but they only seem to work well for local development.
So how do you then have a separate file for a production environment? The dotenv docs say they strongly recommend against a .local.env and .prod.env situation.
Also, how is best to push to a remote server? I have my own server with Gulp tasks which run on a Git post-receive hook. How is best to pass up the production environment variables to here?
Thanks
You could have own config file for each environment:
- environments
- index.js
- deveplopment.json
- staging.json
- production.json
To use appropriate config file, run the app with required NODE_ENV:
NODE_ENV=production node index
In environments/index.js determinate the current NODE_ENV and use config:
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
module.exports = require('./' + process.env.NODE_ENV);
If config file doesn't include secret info (apiKeys, etc), it can be pushed to repo. Otherwise add it to .gitignore and use environment variables on the server.
Note:
For advanced configuration use such packages as nconf.
It allows to create hierarchical node.js configuration with files, environment variables, command-line arguments, and atomic object merging.
Have you thought about having a keys.js file with a .gitignore on it?
I've used this in the past to use module.exports{} to get my variables usable but not going to version control for the security side of things!

Will env. vars affect imports from node_modules?

I'm extracting some utility functions from my project into npm modules so I can use them in other projects.
Some of these functions rely on API Keys, and use different API Keys for DEV and PROD environments.
In the main project, this isn't a problem, as my build process sets the environment vars correctly, and my webpack build process results in the correct keys in the source code.
If I include the API Keys in the npm modules with the same DEV | PROD ternaries, will the environment vars of the main project work the same for the modules as they did for the code when it was in the main project?
// mymodule/index.js
export default function() {
return __PROD__ === true ? "abc" : "123"
// ....
}
// project/index.js in __DEV__ environment
import getKey from 'my-module'
getKey() // should return "123"
I may be misunderstanding your question, but what you're using aren't environment variables. They're probably variables you're filling in with Webpack's DefinePlugin, such as
new webpack.DefinePlugin({
__PROD__: true
})
When Webpack compiles your code, the plugin automatically replaces these magic global variables with the value in the configuration file.
The correct way to use an environment variable in node is process.env, as in process.env.__PROD__, and run your program with something like __PROD__=true node index.js, or by the more common convention NODE_ENV=production node index.js.
If you're publishing the compiled Webpack code to npm, then it should work with whatever DefinePlugin value you've set for the npm compile Webpack configuration.

Resources