How to inject env variables with doppler into react with webpack - reactjs

I have recently switched from using .env file to a secrets management tool, Doppler, and is trying to inject the variables from Doppler into React, which is built by webpack.
However, simply by running
doppler run -- webpack serve --config webpack.dev.js
does not do the trick. What should I do if I want to inject env from Doppler into webpack to build my React app?

I found out about the EnvironmentPlugin in webpack,
When you run doppler run -- webpack serve --config webpack.dev.js, doppler injected the env variables into the runtime and we can pass them with EnvironmentPlugin by specifying the key name in the array and pass that into the plugin
const { EnvironmentPlugin } = require("webpack");
module.exports = {
plugins: [
new EnvironmentPlugin(["SAMPLE_KEY"]),
],
};
Another approach is to pass an object instead, and this approach allows for default values in case doppler has failed to provide the key
const { EnvironmentPlugin } = require("webpack");
module.exports = {
plugins: [
new EnvironmentPlugin({"SAMPLE_KEY":"abcde"}),
],
};
As long as the key specified in either the array or the object matches that in doppler, this should work.
referencing webpack docs here

I'll answer my own question from my comment...since I finally figured it out.
If you are coming from using a .env file in your project - I had a very large one with over 50 lines.
Running from a Unix based IDE You can mount the .env file:
doppler run --mount .env npm run build
This wont work on Windows VSCode, so if you are running your build from Windows based IDE command line (like me), you have to download the .env file
doppler secrets download --no-file --format env > .env
Best practice would be to delete this unencrypted file after processing!!
and using Docker for a CI build on a config branch you will want to run:
doppler run --token ${TOKEN NAME} --mount .env npm run build

Related

Passing env variables to gatsby build or serve in macOS (or linux)

I followed the instructions for additional environment in Gatsby.
It works with command gatsby develop, but when I am using the same for gatsby build command, I see that it uses .env.production and not .env.staging parameters
export ACTIVE_ENV=staging npm run build
gatsby.config file:
let activeEnv =
process.env.ACTIVE_ENV || process.env.NODE_ENV || "development"
console.log(`Using environment config: '${activeEnv}'`)
require("dotenv").config({
path: `.env.${activeEnv}`,
})
It would print that it uses staging env, but the variables in the .js files will be taken from .env.production.
What is wrong?

webpack -p not running on create-react-app

I have a big project which I was trying to reduce in size using webpack-p according to here: https://hackernoon.com/reduce-webpack-bundle-size-for-production-880bb6b2c72f
I could not run it as I was encountering problems when running webpack -p (it threw an error on every function of index.js
I thought it might be something with my packages. I decided to create new create-react-app and run the command there. To my surprise, there I get the same error:
What might be the problem here?
If your app uses webpack v4 you must use webpack --mode=production instead of webpack -p.
Possible values for mode are: none, development or production.
Another usage:
// webpack.config.js
module.exports = {
...
mode: 'production',
...
}
You don't have a config file because the command you are trying to run is global, it is not getting from your current working directory. Run npm run build instead, which does that under the hood, but has a lot of other things created by the contributors of create-react-app.
You could pass a config file for the global webpack cli, but you don't have access for that in your folder since it is "not" available for your. npm run build also already applies a lot of optimizations for you.

ReactJs - Webpack and environment variable

Im tring to build my ReactApp using an environment variable system.
Following online guides, I've create two different files
.env.developtment and .env.production
using the syntax for variables:
REACT_APP_BASE_SERVER_URL=myapp/
During development (using npm start to start the server), development file is loaded perfectly and all variable are stored in process.env global.
Unfortunally after compiling it with webpack, process.env is empty.
Im compiling my code with:
./node_modules/.bin/webpack --config webpack.config.js --env.production --progress --env.NODE_ENV=production --colors
and in my webpack there is no process.env override (using DefinePlugin is the common mistake).
Following a similar question on this site, I've tried to put this command in the config to avoid any process override:
node: {process: false}
but with this process.env will be totally undefined instead of empty ( {} ).
Is it possible to use this kind of environment system or .env files are only supported with npm build?
Sending the env as an argument does not set the application environment. Said so, I considering you are doing it inside your config. What would set up few env values is the option mode as development or production, which is available on webpack4 (You do -p or -d for the previous versions).
I dont know why you said using webpack.DefinePlugin is a common mistake. I have been using it and it works very well.
In last case, if you are sure you process.env should not be empty I would suggest you to do the syntax process.env["expected_attr"].

Gatsby - Unable to set environment variables

In my gatsby-config.js I've used the dotenv package to set env vars
require("dotenv").config({
path: `.env.${process.env.DEPLOY_ENV}`,
});
and then in my package.json a script to deploy to different environments
"deploy:staging": "DEPLOY_ENV=staging gatsby build --prefix-paths && s3-deploy ..."
In my src/html.js, I have an asset that I want to include
<script src={`//${process.env.ASSET_HOST}/app.js`}></script>
When I log the DEPLOY_ENV from gatsby-config.js it is set to staging, however, when I log process.env in src/html.js, ASSET_HOST is set as the one in my .env.production file, so when I deploy to staging it uses assets from my production host.
I think DEPLOY_ENV (as NODE_ENV) is a reserved environment variable. That's why DEPLOY_ENV=staging is not working in your case.
The Gatsby docs on environment variables advices to use a secondary environment variable for additionnal environement support.
You can add a .env.staging file in your root folder, where you put your ASSET_HOST env var.
Then run gatsby with ACTIVE_ENV=staging gatsby develop

Interchangeable API root url

I have a project handled by Webpack and Gulp. All the API's use a singular ROOT_URL variable and append strings to fetch information from the backend.
For multiple deployments I have different back end servers serving from different databases. Currently for each update I have to change the ROOT_URL and bundle the project in each individual server.
Ideally I would like to just pass a bundle to each deployed server so that each one will reference a local JS file containing their respective ROOT_URLs. Is there a way to do this and/or is there an industry standard?
Anytime you have a something that varies by server generally you would use environmental variables. If you need it in your javascript spa's you will have to pass the environmental variable from your server to your javascript(possibly through a templating engine like ejs if your using node). Ultimately how to do this depends on what backend technologies your using.
With Webpack you can specify the config file location. I use this to have separate dev and production configs. You could use this to have a separate config file for each environment that handles updating the ROOT_URL for you.
"scripts": {
"dev": "webpack --config ./src/config/dev.config.js",
"prod": "webpack --config ./src/config/prod.config.js"
},
You can define environment variables using Webpack's DefinePlugin
Imagine you have a deployment script npm run deploy
In your webpack.config.js add a DefinePlugin
module.exports = {
entry: 'app.js',
plugins: [
new webpack.DefinePlugin({
'process.env.API_ROOT': JSON.stringify(process.env.API_ROOT)
})
]
}
Then in your code:
api.js
var url = process.env.API_ROOT + '/resource'
fetch(url).then(function(){
// do stuff
})
Then when you deploy you can define different API roots
API_ROOT=https://api1.com npm run deploy (will deploy code with API 1)
API_ROOT=https://api2.com npm run deploy (will deploy code with API 2)
.. and so forth. Webpack will automatically replace all the occurrences of process.env.API_ROOT in your code with the correct URL.

Resources