At the time of writing, Ionic hasn't any official way to get environment specific configuration variables.
There's an open discussion on GitHub, but everyone is currently on their own about this.
So of course I came up with my own solution.
I'm going to describe it like it was the best solution in the world, like of course everyone should be doing this like I do.
In fact, there's plenty more ways to solve this problem. This is just how I chose to solve it.
Two: dev
(elopment) and prod
(uction).
I'd really like to also have stag
(ing) and test
(ing), but first I'd have to find a better way to triage the current environment than the IONIC_ENV
variable.
JSON files are easy to read, and fairly easy to edit. They also are very easy to import into a node script.
I have two of them:
/config/config-dev.json
/config/config-prod.json
/config/config-dev.json
file:{
"foo": "bar",
"baz": "fooBar"
}
This is an important one: Ionic uses Webpack, and we can specify our own Webpack configuration file. But if we do, the next time we update @ionic/app-scripts
Ionic might stop working because we are missing some new configuration detail.
Instead we keep the official configuration, and expand it.
/package.json
:"config": {
"ionic_webpack": "./config/webpack.config.js"
},
/config/webpack.config.js
and paste this code in it:const webpackConfig = require('../node_modules/@ionic/app-scripts/config/webpack.config');
const webpack = require('webpack');
const ENV = process.env.IONIC_ENV;
const envConfigFile = require(`./config-${ENV}.json`);
const fooConfig = envConfigFile.foo;
const bazConfig = envConfigFile.baz;
webpackConfig.plugins.push(
new webpack.DefinePlugin({
webpackGlobalVars: {
foo: JSON.stringify(fooConfig),
baz: JSON.stringify(bazConfig),
},
})
);
As you can see, we are getting the official Webpack configuration and pushing a new plugin into it. No overrides, just an addition.
Create /src/providers/configuration/configuration.service.ts
.
You may have noticed I don't dig the Ionic CLI proposed convention of naming a service "provider". I also like to always know what kind of file I'm about to open, hence the .service
part of the name.
This is where we use the newly defined webpackGlobalVars
object to inject the environment-driven values into our Ionic / Angular code.
import { Injectable } from '@angular/core';
declare const webpackGlobalVars: any;
@Injectable()
export class ConfigurationService {
public static apiServer = webpackGlobalVars.foo;
public static fooBar = {
bazBaz: 'foo',
fooBar: webpackGlobalVars.baz,
};
// Add more configuration variables as needed
}
I chose to make them static
out of sheer lazyness: this way, I don't have to inject the service: I just import
it and use it: const myConst = ConfigurationService.fooBar
.
Now that I think about it, the @Injectable
decoration might be unnecessary. I'll try to remove it one day or another.
So this is how I tackle the problem of having environment specific variables in Ionic.
Now I will have the values from /config/config-dev.json
when I'm developing the app.
When I use the --prod
flag, I will have the values from /config/config-prod.json
instead.
I think it's fairly concise, effective, and as future proof as it gets.
If you give it a try, let me know!