Environment variable with webpack on dev and production - environment-variables

I am pretty new to the world of using such build tools like Webpack and its relatives, so maybe this question is a little noobish but please understand me.
background: I am developing an client side web app (using reactjs + redux) and using webpack as my build tool and dev-server loader. Right now I have to make some lines of code only in dev environment (logging and stuff). So I saw over the net the usage of webpack.DefinePlugin plugin to set the process.env.NODE_ENV variable and the code is like this:
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development')
})
]
Then if the NODE_ENV varibale is not set on my machine (which is not at the moment) it automatically set to development. Am I right?
What about the production machine? do i need to set this env variable to 'production' in the /etc/environment file?
Then another question is how webpack knows what is the NODE_ENV when I serve the app? is it compiled when I do the build on the production machine and set in the built bundle.js? ($ webpack --progress -p)
Another question is how do I enable/disable features in production or development environment? just do an if condition statement like this:
if(process.env.NODE_ENV == 'development'){
console.log('this is visible in development');
}
And last one, if this is what webpack really does, is it transpiling this piece of code to the built bundle.js? if so, it is visible to end user right? is there something to do with that?
Hope it's not to much, thanks a bunch!

On the production machine you can build your scripts with command
NODE_ENV=production webpack
On the other hand passing this variable to /etc/environment is also solution.
process.env.NODE_ENV is converted to static string in bundle.js
for example if you run NODE_ENV=production webpack on this snippet
if(process.env.NODE_ENV == 'development'){
console.log('this is visible in development');
}
in bundle.js you will find (edited)
if ('production' == 'development') {
console.log('this is visible in development');
}
if (false) { // 'production' == 'development'
console.log('this is visible in development');
}
So according to question about enable/disable features your code is valid.
If you want to remove body of condition if it is false (like in above example you don't want to show console.log('this is visible in development'); in production environment), you should use
new webpack.optimize.UglifyJsPlugin()
It will remove all of your if statements with false condition.

Related

Should the Staging and Production Docker images be the same in Nuxt.js App?

I am developing application Nuxt.js (SPA mode) on the docker, and I am considering hot to deploy nuxt application to staging and production environment.
According to Docker's style, staging and production should be used the same image, but Nuxt.js embeds env at build time, so it needs to be built with staging and production every time.
If you have any best practices on whether Nuxt production deployments should be built every time they are deployed, or whether it is better to use a common image of staing, please let me know.
Thanks in advance.
According to Docker's style, staging and production should be used the
same image, but Nuxt.js embeds env at build time, so it needs to be
built with staging and production every time.
Short answer NO.
.env file should be ingnored in git and fill by secrets in your CI before build with docker or manually write on your production enviroment.
You can be use two .env files either:
.env
.env.prod
Add this at the top of your nuxt.config.js file.
const fs = require('fs'),
path = require('path');
if(process.env.NODE_ENV === 'production' && fs.existsSync('.env.prod')){
require('dotenv').config({ path: path.join(__dirname, `.env.prod`)});
} else{
require('dotenv').config();
}

Heroku environment variables not set in javascript for React/Rails application

I've built a Rails-Api with React SPA frontend following this guide (very helpful, would recommend). I'm having issues getting Heroku to set the environment variables in the .env file that React uses for config vars. The values of the file are just set as literally "ENV[...]" instead of evaluating and setting the value. On the Rails side the Heroku ENV vars are being set correctly because I can see them in the console.
.env file:
REACT_APP_API_KEY=ENV['API_KEY']
REACT_APP_AUTH_DOMAIN=ENV['AUTH_DOMAIN']
App.js (top level Component):
console.log(config,process.env);
// which logs:
{
NODE_ENV: "production"
REACT_APP_API_KEY: "ENV['API_KEY']"
REACT_APP_AUTH_DOMAIN: "ENV['AUTH_DOMAIN']"
...
}
Rails Console:
irb(main):001:0> ENV
=> {"LANG"=>"en_US.UTF-8", "NODE_ENV"=>"production",
"API_KEY"=>"<correct-value>", "AUTH_DOMAIN"=>"<correct-value>",......}
Is there something I need to do in order to alert Heroku that the ENV vars need to also be set in the .env file for the react app? The tutorial has the Heroku deployment use both the nodejs and ruby buildpacks (in that order). The app is built and then copied into the "public" dir for Rails to serve:
package.json
{
//...
"engines": {
"node": "12.9.0",
"yarn": "1.22.4"
},
"scripts": {
"build": "yarn --cwd client install && yarn --cwd client build",
"deploy": "cp -a client/build/. public/",
"heroku-postbuild": "yarn build && yarn deploy"
}
}
I don't know enough about the internal workings with Heroku's env vars swap. From what I understand with Create React App... the .env file's contents are set at build time so it is possible that the js is compiled before Heroku has any chance to inject the env vars. I'm open to suggestion on other ways to do this if this method isn't doable. Thanks!
You can expand environment variables in .env file. When React app is built, it has access to variables in your Heroku dyno, and react-scripts supports referencing them in your .env file. See more in docs.
With this in mind, your .env file would look like:
REACT_APP_API_KEY=$API_KEY
REACT_APP_AUTH_DOMAIN=$AUTH_DOMAIN
Assuming API_KEY and AUTH_DOMAIN variables are set in Heroku.
If you name these variables REACT_APP_API_KEY and REACT_APP_AUTH_DOMAIN in Heroku in the first place, then they will be picked up by react-scripts directly from the environment (no need for .env file then)
NOTE: with the above said, it sounds like you are trying to expose secrets in React app. The Create React App docs strongly warns NOT to do that, because:
Environment variables are embedded into the build, meaning anyone can view them by inspecting your app's files.

Will app.json post-deploy script run on production env as well as review apps?

I'm using Heroku + Rails 5.1.
I just want my postdeploy script written in app.json to run only in Review Apps environment.
I have done something like this by setting a config var in my staging environment (the parent for my review apps) which tells my postdeploy that it is not in production. I added the cli webpack to app.json and inside my postdeploy I get the value of that config var and then conditionally execute code. In production, we set a different var.
You could also just check the $HEROKU_PARENT_APP_NAME inside the review app (you must have this env var defined in app.json for it to appear in review app), and if the parent app == staging (or whatever), don't execute whatever is in your post deploy
good luck, getting review apps to work right can be a huge pain

How to programmatically know if I am building with -prod flag (ng build -prod)

I am using docker so, in production mode I am using linked containers with URLs like "http://api:3000/"
instead of "http://localhost:3000/" while in dev mode.
I would like to be able to use "http://api:3000/" if "ng build -prod" and stay with "localhost" while developing.
How can I do my if( "-prod" ) ?
Thanks for reading me, I hope my question is clear.
EDIT: Everything was explain in a commentary in environment.ts
You have environments/environment.ts, and there is a json
export const environment = {
production = false
};
And you can access it within your application with importing it and then using it with if(environment.production)
or use the built in angular module like in
How to check if Angular 2 app is running in production or dev

How to set up and use Rails environment variables in production server?

I need to set up an environment variable for my rails app. Both in my local machine and in the production server. I read some tutorials on the internet but NONE has given the complete instruction on how to set and use these variable in the actual production server. I use digital ocean and linux server to host my rails app.
I have spent days trying to figure this out, but still haven't found a clear and complete instruction from setting the variables on my local machine -> push it to git repo -> set and use the variables in production server. So, hope somebody can help me here, thanks!
UPDATE:
This is how I currently setup the environment variables in my rails app by using figoro gem:
You can set system-wide environment variables in the /etc/rc.local file (which is executed when the system boots). If your Rails app is the sole user of the Linux system, that is a good place to store credentials such as API keys because there is no risk of including this file in a public Git repository, as it is outside the application directory. The secrets will only be vulnerable if the attacker gains shell access to your Linux server.
Set the environment variables within /etc/rc.local (do not include the <> characters):
export SOME_LOGIN=<username>
export SOME_PASS=<password>
To see the value of an environment variable, use one of the following commands in the Linux shell:
printenv MY_VAR
echo $MY_VAR
To access those environment variables within Rails, use the following syntax:
Inside .rb files or at the rails console
ENV['MY_VAR']
Inside .yml files:
<%= ENV['MY_VAR'] %>
For anyone still having this issue, figaro now has an easy method in setting the production variables in heroku. Just run:
$ figaro heroku:set -e production
ryzalyusoff.
For Unix
You can use LINUX ENV in rails application.
# .env
GITHUB_SECRET_KEY=SECRET
TWITTER_ACCESS_KEY=XXXXXXXXXXXX
# in rails code
puts ENV["TWITTER_ACCESS_KEY"] # => SECRET
Create .env files for local machine and your production server. Export environment variables like this(on server with ssh):
export GITHUB_SECRET_KEY="XXXXXXXXXXXXXXXXXX"
Anyway, storing keys in config - bad idea. Just add .env.example, others keys configs add to .gitignore. Goodluck.
Example with Rails
For Windows
Syntax
SET variable
SET variable=string
SET /A "variable=expression"
SET "variable="
SET /P variable=[promptString]
SET "
Key
variable : A new or existing environment variable name e.g. _num
string : A text string to assign to the variable.
expression : Arithmetic expression
Windows CMD
I believe we should not push a secret file on git.
To ignore such file use gitignore file and push other code on the git.
On the server side just copy the secret file and create a symlink for that file.
You can find demo here http://www.elabs.se/blog/57-handle-secret-credentials-in-ruby-on-rails
You can set your environment variables in production in the same way, you do it for local system. However, there are couple of gems, which make it easier to track and push to production. Have a look at figaro. This will help you in setting up and deployment of env vars.
You can do this with figaro gem
or in rails 4 there is a file named secret.yml in config folder where you can define your environment variables this file is by default in .gitignore file.For production you need to manually copy that file to server for security reason so that your sensitive information is not available to any one
First create your variable like:
MY_ENV_VAR="this is my var"
And then make it global:
export MY_ENV_VAR
You can check if the process succeeded with:
printenv
Or:
echo MY_ENV_VAR

Resources