I'm building an Ionic3
application, and my config.xml
have some data that I want to be able to change according to my environment (for example, I want that my facebook app id have different values for development, staging and production).
I achieved this creating a template config.xml
(the file is config.tpl.xml
) and a before_prepare
cordova
hook to replace the variables in the template with the correct values and save the generated content in config.xml
.
The cordova
hook uses the npm
package es6-template-strings
:
npm install es6-template-strings --save-dev
The hook is:
#!/usr/bin/env node
var fs = require('fs');
var path = require('path');
var compile = require('es6-template-strings/compile');
var resolveToString = require('es6-template-strings/resolve-to-string');
var ROOT_DIR = process.argv[2];
var FILES = {
SRC: "config.tpl.xml",
DEST: "config.xml"
};
var env = process.env.NODE_ENV || 'dev';
var envFile = 'src/environments/environment.' + env + '.json';
var srcFileFull = path.join(ROOT_DIR, FILES.SRC);
var destFileFull = path.join(ROOT_DIR, FILES.DEST);
var configFileFull = path.join(ROOT_DIR, envFile);
var templateData = fs.readFileSync(srcFileFull, 'utf8');
var configData = fs.readFileSync(configFileFull, 'utf8');
var config = JSON.parse(configData);
var compiled = compile(templateData);
var content = resolveToString(compiled, config);
fs.writeFileSync(destFileFull, content);
I have files in the src/environments/
directory for different environments, that are chosen based on the NODE_ENV
value that is defined when I build cordova
. For example, if NODE_ENV=prod
(production), then it would use the file environment.prod.json
:
{
...
"FACEBOOK_APP_ID": "11111111",
"FACEBOOK_APP_NAME": "My Facebook App Name",
...
"PUSH_SENDER_ID": "22222222",
...
}
When the hook is executed, this part in the cordova.tpl.xml
:
<plugin name="cordova-plugin-facebook4" spec="~1.7.4">
<variable name="APP_ID" value="${FACEBOOK_APP_ID}" />
<variable name="APP_NAME" value="${FACEBOOK_APP_NAME}" />
</plugin>
<plugin name="phonegap-plugin-push" spec="~1.9.2">
<variable name="SENDER_ID" value="${PUSH_SENDER_ID}" />
</plugin>
becomes like:
<plugin name="cordova-plugin-facebook4" spec="~1.7.4">
<variable name="APP_ID" value="11111111" />
<variable name="APP_NAME" value="My Facebook App Name" />
</plugin>
<plugin name="phonegap-plugin-push" spec="~1.9.2">
<variable name="SENDER_ID" value="22222222" />
</plugin>
So far so good. The problem is that when some automatic changes are done to config.xml
(like adding plugins), it is not reflected in cordova.tpl.xml
, so I have to remember to make the changes manually.
Although the way it is done now is still much better than having to add each environment variable like before (it was a maintenance nightmare and error prone), I still have to change the template every-time a add/change/remove a plugin (not so frequent, and easy to discover the problem when I forget it, but still far from the ideal).
I would like to know if there is a way avoid these manual changes, but keep using the environment variables like I'm doing now.
It could be achieved making the automatic changes to config.xml
to be done to config.tpl.xml
instead (like when adding a plugin with --save
), if possible, but I haven't found any cordova
option about this.
Or using the config.xml
as the template and send it to another place with the variables defined (e.g. to www/config.xml
), and use the config.xml
in the other location to be used to build the app (not the config.xml
in the root, i.e., the template). I would only change the src
and dest
files in my hook (to config.xml
and www/config.xml
, respectively). But I also haven't found a way to achieve this.
Any thoughts about this?
(It doesn't need to be an Ionic specific solution.)
Based on Bobby's answer, I achieved what I wanted both when installing and uninstalling a plugin. I've created 4 hooks: after_plugin_add
, after_plugin_rm
, before_plugin_add
, before_plugin_rm
.
The before
hooks copy the template (config.tpl.xml
) into the config.xml
file and the after
hooks do the inverse.
The before_plugin_add
and before_plugin_rm
hooks are as follows:
#!/usr/bin/env node
var fs = require('fs');
var path = require('path');
var ROOT_DIR = process.argv[2];
var FILES = {
SRC: 'config.tpl.xml',
DEST: 'config.xml'
};
var srcFileFull = path.join(ROOT_DIR, FILES.SRC);
var destFileFull = path.join(ROOT_DIR, FILES.DEST);
var templateData = fs.readFileSync(srcFileFull, 'utf8');
fs.writeFileSync(destFileFull, templateData);
The after_plugin_add
and after_plugin_rm
hooks are almost identical, just swapping FILES.SRC
and FILES.DEST
values.
The Cordova config. xml file is the global configuration file of the application. The Cordova configuration file is a mandatory XML file that contains application metadata, and is stored in the root directory of the app.
config. xml is a global configuration file that controls many aspects of a cordova application's behavior. This platform-agnostic XML file is arranged based on the W3C's Packaged Web Apps (Widgets) specification, and extended to specify core Cordova API features, plugins, and platform-specific settings.
When adding plugins or platforms, use the --save flag to add them to config. xml. Ex: cordova platform add android --save. Existing projects can use cordova plugin save and cordova platform save commands to save all previously installed plugins and platforms into your project's config.
Each WebLogic Server domain contains a central configuration file called the config. xml, which is stored in the DOMAIN_HOME\config directory. Both the Admin Server and the Managed Servers derive their run-time configuration information from the config.
One solution could be to create hooks for before_plugin_install and after_plugin_install.
On before_plugin_install copy the cordova.tpl.xml to cordova.xml.
... Plugin is installed ...
On after_plugin_install copy cordova.xml to cordova.tpl.xml
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With