Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access environment variables from the front-end

I have defined several environment variables in the compilation script. But, I have only access to this variables only from webpack.config.babel.js file and I need to get access to this variables in react code (front-end).

I have found a way to do this here: https://blog.container-solutions.com/deploying-configurable-frontend-web-application-containers, but I don't think it would be a good idea to put in meta tags data like database passwords, for example. Despite of, trying to do only the way for .env file it doesn't work to me :(

So, my question, is how can I get access to environment variables from the front-end?

Edit I:

I have applied the wise advice of @robi932 but it doesn't work to me :(

webpack.config.babel.js

plugins: [
    new HtmlWebpackPlugin({
        template: "./src/client/index.html",    //where is our template
        filename: "../index.html",              //where we are going to put our index.html inside the output directory
        minify: {
            collapseWhitespace: true,
            removeComments: true,
            removeRedundantAttributes: true,
            removeScriptTypeAttributes: true,
            removeStyleLinkTypeAttributes: true,
            useShortDoctype: true
        }            
    }),
    new MiniCssExtractPlugin({
        filename: "css/bundle.css",
        minify: {
            collapseWhitespace: true,
            removeComments: true,
            removeRedundantAttributes: true,
            removeScriptTypeAttributes: true,
            removeStyleLinkTypeAttributes: true,
            useShortDoctype: true
        }             
    }),
    new webpack.DefinePlugin({
        URL_FEB_API: JSON.stringify(process.env.URL_FEB_API)
    })

I define the const URL_FEB_API to use it later on my react-js code, but when I try to access to it, it doesn't work :(

console.log("HomeLF1Content process.env.URL_FEB_API: " + URL_FEB_API);

or

console.log("HomeLF1Content process.env.URL_FEB_API: " + process.env.URL_FEB_API);

This is my compiling scripts in package.json:

    "clean": "rm -rf ./dist",
    "compile-dev": "NODE_ENV=development URL_FEB_API=http://localhost:4000/api/feb/graphiql webpack -d --config ./webpack.config.babel.js --progress",
    "dev": "npm run clean && npm run compile-dev && cross-env NODE_ENV=development nodemon --exec babel-node src/server/server.js --ignore ./src/client"

What am I doing wrong?

Solution:

Thanks to this link https://medium.com/@trekinbami/using-environment-variables-in-react-6b0a99d83cf5 give it by @Shubham Jain, finally I have found a good solution to define environment variables for the front-end.

Then, I'm going to explain what have been the steps that I have followed to solve my problem.

First, we need two .env files for each environment. Now, we have two environments: development and production. So, .env.development will be the file where we are going to config all our development variables and .env will be the file where we are going to config all our production variables.

Second, to select one of those files created before, we need to say it to node which file to make the compilation, so in our compiling scripts we have to define a variable that we are calling NODE_ENV where we are going to initialize with "development" or "production".

development scripts:

"clean": "rm -rf ./dist",
"compile-dev": "NODE_ENV=development webpack -d --config ./webpack.config.babel.js --progress",
"dev": "npm run clean && npm run compile-dev && cross-env NODE_ENV=development nodemon --exec babel-node src/server/server.js --ignore ./src/client",

production scripts:

"clean": "rm -rf ./dist",
"compile": "NODE_ENV=production webpack -p --config ./webpack.config.babel.js --progress",
"start": "npm run clean && npm run compile && cross-env NODE_ENV=production babel-node src/server/server.js --ignore ./node_modules",

Third, now, we are going to ad some code to our webpack.config.babel.js file to select the environment variables depending of the value of NODE_ENV variable.

import webpack from "webpack";
import path from "path";
import dotenv from "dotenv";
import fs from "fs";
/**
 * Code to get the values of environment variables during compilation time for the front-end
 */
//Get the root path. Our .env files and webpack.config.babel.js files are in the root path
const currentPath = path.join(__dirname);
const basePath = currentPath + "/.env";
// We're concatenating the environment name to our filename to specify the correct env file!
const envPath = basePath + "." + process.env.NODE_ENV;
// Check if the file exists, otherwise fall back to the production .env
const finalPath = fs.existsSync(envPath) ? envPath : basePath;
// Set the path parameter in the dotenv config
const fileEnv = dotenv.config({ path: finalPath }).parsed;
// reduce it to a nice object, the same as before
const envKeys = Object.keys(fileEnv).reduce((prev, next) => {
  prev[`process.env.${next}`] = JSON.stringify(fileEnv[next]);
  return prev;
}, {});

Fourth, in webpack.config.babel.js file too, in the plugin section, we have to add the access to this variables when compiling the project:

plugins: [
    //With this entry we can get access to the environment variable for front-end
    new webpack.DefinePlugin(envKeys),
],

And finally, to get access to these variables in the front-end, we can access to them easily with process.env.VARIABLE_NAME where VARIABLE_NAME is one of the variables defined in the files .env or .env.development.

Please, vote the answer give it by @Shubham Jain, because his link has been very useful to me.

like image 268
José Carlos Avatar asked Aug 26 '19 19:08

José Carlos


People also ask

How do I access environment variables?

On the Windows taskbar, right-click the Windows icon and select System. In the Settings window, under Related Settings, click Advanced system settings. On the Advanced tab, click Environment Variables.

Can a browser access environment variables?

By default environment variables are only available in the Node.js environment, meaning they won't be exposed to the browser. This loads process.env.NEXT_PUBLIC_ANALYTICS_ID into the Node.js environment automatically, allowing you to use it anywhere in your code.

How can I see my current environment variables?

To display your current environment variables, use the env command. An environment variable that is accessible to all your processes is called a global variable.


3 Answers

There is a very simple way to to that:

Step one: Go to the root folder of your application and create a text file called .env.

Step two: Create your custom variables in the new file. Create React App(CRA) enforces the prefix REACT_APP on every custom variable. Please note that variables without the prefix are ignored during bundling.

REACT_APP_CLIENT_ID=jfjffffaddfeettgydgdffv
REACT_APP_KEY=aaddddawrfffvvvvssaa

Step three: Assign them to variables, print them to the screen etc, but they are read-only from your Javascript file.

console.log(process.env.REACT_APP_CLIENT_ID); 
console.log(process.env.REACT_APP_KEY);

Step four: There is a built-in environment variable called NODE_ENV. You can access it from process.env.NODE_ENV. This variable changes based on what mode you are currently in. When you run npm start, it is equal to ‘development’, when you run npm test it is equal to ‘test’, and when you run npm run build it is equal to ‘production’. This variable is special as it can be used to access different environment configurations based on your mode. For example, if you have different databases for your production and development (usually to prevent interference) you can use it to conditionally access certain variables. The fact that you cannot override NODE_ENV manually prevents developers from accidentally deploying a development build to production.

Step five: Open the .gitignore file. I like to put .env and other environment variables under #misc.

Why Isn’t It Working Even After Following These Processes?

  • Make sure you used the prefix REACT_APP on every variable

  • Confirm that the variable names on the .env file match the ones on your js file. For example,REACT_APP_KEY in .env versus process.env.REACT_APP_KY

  • If the development server was running, stop it then rerun using npm start it. I really struggled with this (variable is undefined error). Every time you update the .env file, you need to stop the server and rerun it, as the environment variables are only updated during build (variable is undefined error).

  • Remove quotations from the values of the variables.

Wrong

REACT_APP_KEY=”AHEHEHR”

Right

REACT_APP_KEY=AHEHEHR

Note: Putting Sensitive content to environment variables doesn’t make them safe. They are injected into the bundled file during the build process so anyone can see them by inspecting your files. I have found their greatest use to be hiding the information before pushing my code to a remote repository.

like image 58
Raul Avatar answered Oct 01 '22 03:10

Raul


I case you want straight forward solution. there's 3rd party library for this called dotenv-webpack. More info here

const Dotenv = require('dotenv-webpack');

module.exports = {
  ...
  plugins: [
    new Dotenv()
  ]
  ...
};
like image 32
Jasper Bernales Avatar answered Oct 02 '22 03:10

Jasper Bernales


You can use the following methods if you are from windows, if you are from linux then the methods are straight forward. You might not have encountered this problem with linux as dotfile are a thing in linux

Method 1 : dotenv in windows

This step might be necessary to access elements from a .env file in windows

npm install dotenv

then create a .env file in the root folder

API_KEY='SomeAPIkey'
API_PASS='ReallySecretPassword12345'

' is not necessary unless you have some strings seperated by space

and in your main.js file import the dotenv package

const dotenv = require("dotenv");

dotenv.config({ path: ".env" });

const key = process.env.API_KEY;
console.log(key);

if you are from linux you don't require the dotenv package for this to work.


Method 2: environment variables through terminal

+ in cmd

set API_KEY='SomeAPIkey'
set API_PASS='ReallySecretPassword12345'

+ in powershell

$env:API_KEY='SomeAPIkey'
$env:API_PASS='ReallySecretPassword12345'

+ in bash / wsl

export API_KEY='SomeAPIkey'
export API_PASS='ReallySecretPassword12345'

main.js

const key = process.env.API_KEY;
console.log(key);

The problem with method 2 is that your env variables live only as long as you keep the terminal session open. As soon as you close your terminal or shutdown your computer your env variables will be lost. I would recommend you to try and create a scripting file and add its filename to .gitignore

like image 5
Jo_L Avatar answered Sep 30 '22 03:09

Jo_L