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