Here my solution.
Consider to have some environments where "you know configurations" and other environments where "you don't know configuration", but they must be configured by system administrators.
For example 3 environments: local and uat where you know configurations, and production where you don't know configuration to set.
So, I wan't that a config file is automatically generated for specific environment, and this config file must be editable
We can use a config.js file where put a json object.
So, first go in index.html and add in head
<script src="config.js"></script>
This means that config.js file must be in compiled root folder (same position of index.html), that means inside react solution "public" folder.
But we want that this config.js is dynamic based on environment.
Consider to create in react solution root folder a folder called "config".
Put in this folder 3 files: config_local.js, config_uat.js, config_prod.js
-config_local.js
var Configs = {
API_ENDPOINT':"http://local:88/service"
}
-config_uat.js
var Configs = {
'API_ENDPOINT':"http://uat:88/service"
}
-config_prod.js
var Configs = {
'API_ENDPOINT':""
}
We need to copy one of this 3 files inside root folder, renaming output file to "config.js"
So, first we need to have a .env file for each envirorment.
In this env file we want just set the filename that will be copied in root folder.
So create a .env, .env.uat, .env.local, .env.prod in react root folder
-.env (this is default)
REACT_APP_CONFIG_FILE=config_prod.js
-.env.local
REACT_APP_CONFIG_FILE=config_local.js
-.env.uat
REACT_APP_CONFIG_FILE=config_uat.js
-.env.prod
REACT_APP_CONFIG_FILE=config_prod.js
We need to add/replace scripts object in package.json.
Before we need to install env-cmd (npm install env-cmd). Here an example of scripts
"scripts": {
"start": "env-cmd -f ./.env react-app-rewired start",
"build": "env-cmd -f ./.env react-app-rewired build",
"test": "env-cmd -f ./.env react-app-rewired test",
"start:local": "env-cmd -f ./.env.local react-app-rewired start",
"build:local": "env-cmd -f ./.env.local react-app-rewired build",
"start:uat": "env-cmd -f ./.env.uat react-app-rewired start",
"build:uat": "env-cmd -f ./.env.uat react-app-rewired build",
"start:prod": "env-cmd -f ./.env.prod react-app-rewired start",
"build:prod": "env-cmd -f ./.env.prod react-app-rewired build"
},
PS: I've used react-app-rewired. I need it because we need to use a CopyFile plugin, but I can't set it in webpack, because my app is created with create-react-app.
So, if you haven't webpack file, install rewired with npm install react-app-rewired
Now, we need to copy specific js file based on specific environment.
So install copyfile with npm install copy-webpack-plugin
Example if we don't have webpack:
Create in react root folder a file called "config-overrides.js" e copy this content:
const CopyWebpackPlugin = require('copy-webpack-plugin');
let internal_env = process.env.REACT_APP_CONFIG_FILE || 'config_prod.js';
module.exports = function override(config, env) {
if (!config.plugins) {
config.plugins = [];
}
config.plugins.push(
new CopyWebpackPlugin(
[
{
from: 'config/' + internal_env,
to: './config.js'
}
])
);
return config;
};
So, in our react files, we can read configuration with:
//@ts-ignore
const apiEndpoint = Configs.API_ENDPOINT || ''
NB: if you use typescript, you need to ignore, because we can't import configs as module
So, now you can start or build using one of this, based on desired environment:
npm run start
npm run build
npm run start:local
npm run build:local
npm run start:uat
npm run build:uat
npm run start:prod
npm run build:prod
When you can build, specific config.js is generated in root app folder and can be editable (for example by system administrators)