Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cordova config.xml environment variables

Tags:

ionic3

cordova

The Scenario:

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>

The problem:

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).

My question:

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.)

Update (2017-10-13)

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.

like image 807
Lucas Basquerotto Avatar asked Sep 21 '17 13:09

Lucas Basquerotto


People also ask

Where is config xml in cordova?

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.

What is config xml file in cordova?

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.

How do I add a plugin to config xml cordova?

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.

Where do I find config xml?

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.


1 Answers

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
like image 113
Bobby Avatar answered Oct 13 '22 08:10

Bobby