How can I set up a node app (ember app kit) on heroku that reads ENV variables and makes the values available to the application? - node.js

Okay, I'm new to node, and really only just using the node server to serve static js, but I can't find any info on this anywhere.
I'm running an application ember app kit, which gets built to a node server.js for deploy, and heroku runs it with node server.js.
It uses grunt for building, testing, etc.
I'd like to know how I can specify configuration variables (i.e. authentication tokens) that can be overridden by heroku config variables.
The closest I've been able to get is a custom task that reads environment variables and writes out a json file that gets built into the site (and assigned to a global var). This works locally, but doesn't take into account heroku configs.
I even wrote a deploy script that gets heroku's configs, exports them as environment variables locally, and does the build--Which works, but the configs only get updated on app deploy. So if I do a heroku config:add CONFIG_TEST=test_value, my app doesn't see that value for CONFIG_TEST until the next time I deploy the app.
I'd like for my app to start embedding that config value in the browser JS immediately.
Any way to do this with node the way my app is set up?

I am not sure I understand what's wrong with simply taking config variables, at run time, from the environment. Use process.env.KEY in your code, and embed that result into whatever template you may have, and serve that as the result.
When you change Heroku config variables your process gets restarted, so it picks up the new values.
Is the problem the fact that you serve static files? If so -- can you simply change it so that you use a template engine to do some processing on them before serving?

OK, here's a solution for ember-app-kit using grunt-sed.
In EMBER_APP_KIT_PROJECT/tasks/options/sed.js
Add something like
module.exports = {
version: {
path: "./dist/",
pattern: '{{env.API_BASE_PATH}}',
replacement: function(){
return process.env.API_BASE_PATH;
},
recursive: true
}
};
then in your code just put
"{{env.API_BASE_PATH}}"
Now, when you run
$ grunt sed
it will replace "{{env.API_BASE_PATH}}" with whatever's in the environment variable.

Related

getting 401 response codes on a deployed React App that worked fine in development?

I am trying to complete a Redux project and got everything to work fine in development on my own machine but when deployed, the browser is failing to recognise my hidden environment variables so not passing client keys to Api calls and thus making unauthorised requests. I have a '.env' file with the keys in them and then refer thus...
const API_URL = https://api.openweathermap.org/data/2.5/weather?appid=${process.env.REACT_APP_OPEN_WEATHER_MAP_API_KEY}&units=metric;
I have looked up the problem on here and think I understand what's going wrong but don't know how to put it right. I am deploying site via Netlify from my Github repo and my build settings appear to be correct. I thought 'npm run build' took care of all that for me?
99% finished a project and now scratching my head furiously...
Try defining variables in .env file starting with REACT_APP like:
REACT_APP_CLIENT_ID=4
REACT_APP_API_URL=/api
Try using it anywhere like:
const apiUrl: process.env.REACT_APP_API_URL;
Set the environment variables specifically within the Netlify UI. So 'Deploy Settings > Environment > Environment Variables' then variable -'REACT_APP....' value - '*****' for each variable you want defined.

Environment variables in NodeJs using cPanel

So I'm using cPanel with Setup Node.js App plugin for a Next.js app. (don't asky why cPanel)
Everything is working as expected in development, except for environment variables in production, I set up them manually from the cPanel interface, I restarted/stopped the app, logging the process.env on the server and I don't see the env variables there (not to say when trying to call them they are undefined).
When doing
res.json(JSON.stringify(process.env)); i get a bunch of variables except for the one I manually wrote in cPanel variables interface.
It is important for me to store these variables as secret key because they are API credentials.
Anyone know what I might have misconfigured or had this problem?
Never mind, found the answer, apparenlty was a Next.js misconfiguration. I had to add the following lines of code inside next.config.js in order to read env variables on build version.
require('dotenv').config();
module.exports = {
env: {
EMAIL_NAME: process.env.EMAIL_NAME,
EMAIL_PASSWORD: process.env.EMAIL_PASSWORD,
GETRESPONSE_API_KEY: process.env.GETRESPONSE_API_KEY
}
};
Where EMAIL_NAME, EMAIL_PASSWORD, GETRESPONSE_API_KEY were the variables defined by me on cPanel interface

Why is process.env returning an empty object, while process.env.prop returns the prop value?

So I have the simplest example on a node machine running with a react-redux app with webpack (Though I don't think any of this matters for the issue expect it being on nodejs).
Specific calls get a value pack:
console.log(process.env.NODE_ENV); // output: 'development'
General calls get nothing back:
console.log(process.env); // output: {}
What am I missing here?
Addition info the might be relevant:
I am using dotenv for the test environment.
I am using dotenv-webpack for the development environment.
I am not using neither of those for the production environment deployed to Heroku
The problem persists on all environments.
The issue with process.env variable being empty in browser is because browser doesn't have real access to the process of the node.js. It's run inside the browser though.
Usage of process.env.ANYTHING is usually achieved by plugins like https://webpack.js.org/plugins/define-plugin/ which just simply replace any occurrence of process.env.ANYTINHG with env variable during BUILD time. It really does just simple str.replace(/process.env.ANYTING/value/) this needs to be done during build time as once you output dist bundle.js you don't have access to the ENV variables.
Replacing during build time
Therefore you need to be sure that when you are producing production build e.g with yarn build you are using webpack.DefinePlugin and replacing those process.env calls with current ENV values. They can't be injected in runtime.
Injecting in runtime
When you need to access env variables in runtime it's basically impossible in JavaScript in browser. There are some sort of hacks for example for NGINX which can serialize current env variables to the window.ENV variable and in your app you will not use process.env but window.ENV. So you need to either have ENV variables available while you are building the application or build mechanism which will dynamically output current ENV as json to window and access with react. If you are using docker it can be done with ENTRYPOINT otherwise you need some bash script which will always output current ENV variables as JSON to the index.html of your app

How to get Heroku to ignore a failed import?

I've got a project deployed on heroku using React and node, for which I'm importing a json file which contains various API keys (for firebase, AWS, etc.). In development, I simply do import keys from './keys.json'. However I was aware that wouldn't work in Heroku, so I set up the appropriate environment vars and used process.env to get them. Now though... the whole compilation/build of my project fails because Heroku can't find keys.json (since I don't deploy it, for apparent reasons). Is there any way to get it to ignore this one particular failure during build so it can go ahead and use the env vars?
Wrap the import in a conditional:
var keys = {}
if (!process.env['AWS_KEY']) {
keys = require('./keys.json')['keys'];
}
This has the side effect of giving precedence to environment variables over a local file. If you want the file to have precedence instead, look at fs.existsSync as your conditional (fs.exists could be used with some work).

Change configuration in runtime by changing environment variables using the module node-config

I'm trying to use the node-config module to change some parameters of my configuration (basically logging level) during runtime.
In the official documentation says:
Environment variables can be used to override file configurations. Any environment variable that starts with $CONFIG_ is set into the CONFIG object.
I've checked that this is true when the server starts but it does not seem to work once it's up. (The handler of the watch function is never called when an environment variable is changed unlike a change in the runtime.json file or directly changing a config variable).
I'm currently watching the whole CONFIG object like this:
var CONFIG = require('config');
CONFIG.watch( CONFIG , null , function(object, propertyName, priorValue, newValue){
console.log("Configuration change detected");
});
Does anyone know if this is possible?
The environment is available during startup of a process.
If the process is running, you won't be able to change the environment anymore, the process is in.
The only option is to restart the process or use other mechanisms to communicate with it.
Say for example having a rest or tcp listener inside, where you can transfer your variable inside.
Best regards
Robert
As you must knowing, React is a single page application which is eventually when it is complied is a static page app that means all the files of the react application is complied into vanilla JS and CSS file bundle in a Tarball. Now that Tarball is eventually deployed on a web server. It could be Apache web server, nginx web server or anything which you are using it but an important point is the static app is running in someone else browser and someone access to website CSS and JS are downloaded in a browser and it is running in the browser runtime environment so technically you cannot have a runtime environment variable for someone else browser but may be there would be a way to access them during runtime.
SOLUTION
I have achieved this goal with the package called runtime-cra.
follow the steps on this official documentation: https://blog.risingstack.com/create-react-app-runtime-env-cra/

Resources