[英]Using environment variables / parameterizing config.xml
我正在使用cordova-plugin-facebook4插件构建一个离子/ cordova项目,用于Facebook身份验证访问。 在config.xml
这看起来像:
<plugin name="cordova-plugin-facebook4" spec="~1.7.1">
<variable name="APP_ID" value="1234567890123456"/>
<variable name="APP_NAME" value="My_Appy_App"/>
</plugin>
这APP_ID
,但我们使用的APP_ID
是针对开发应用程序,我们有一个单独的Facebook应用程序用于其他环境,如QA。
有没有办法在config.xml
参数化这些变量并将它们作为构建步骤的一部分进行替换? 就像是:
<plugin name="foo" spec="~0.0.0">
<variable name="bar" value="${env.APP_ID}"/>
</plugin>
...然后运行APP_ID=baz ionic build android
或类似的东西。
我没有在cordova文档中看到任何允许您这样做的内容。
@Ghandi使用cordova钩子的解决方案就是如何实现这一点的一个很好的例子,尽管它只是专门用于Windows,因为它使用批处理文件和PowerShell作为钩子脚本。
作为跨平台解决方案,您可以在cordova之上使用某种构建工具。 对于我正在进行的项目,我们在子目录中有一个cordova项目,并且已经使用gulp来构建我们应用程序的其余部分,因此我们修改了我们的任务,将我们的cordova资产复制到构建目录以使其也执行搜索并在config.xml
替换。 它从环境变量中提取替换,并使用dotenv库从.env
文件(未检入存储库)加载环境。
var gulp = require('gulp'),
replace = require('gulp-replace'),
gutil = require('gulp-util'),
filter = require('gulp-filter'),
path = require('path'),
dotenv = require('dotenv'),
argv = require('yargs').argv,
isRelease = !!(typeof argv.release !== 'undefined' ? argv.release : (typeof argv.r !== 'undefined' ? argv.r : false));
gulp.task('cordova_assets', ['clean', 'templates'], function() {
dotenv.config({path: path.join(__dirname, 'cordova', '.env'), silent: true});
var f = filter(['cordova/config.xml'], {restore: true});
return gulp.src(['cordova/**/*'], {base: './'})
.pipe(f)
.pipe(replace(/\$\$([A-Z0-9_]+)/gi, function(substr, varname) {
var repl = '';
if(!isRelease && typeof process.env[varname + '_DEBUG'] !== 'undefined')
repl = process.env[varname + '_DEBUG'];
else if(isRelease && typeof process.env[varname + '_RELEASE'] !== 'undefined')
repl = process.env[varname + '_RELEASE'];
else if(typeof process.env[varname] !== 'undefined')
repl = process.env[varname];
else {
throw new gutil.PluginError('cordova_config', {
message: 'expected but could not find the environment variables "' + varname +
'" or "' + varname + '_' + (isRelease ? 'RELEASE' : 'DEBUG') + '" which is used in cordova/config.xml. ' +
'Add it to cordova/.env or specify them explicitly when running the build command.'
});
}
console.log('replacing "%s" with "%s"', substr, repl);
return repl;
}))
.pipe(f.restore)
.pipe(gulp.dest('build'));
});
它将替换config.xml中以两个美元符号开头的任何变量,并且由字母数字字符和下划线组成,如果存在,则包含相应环境变量的值(如果不存在,则抛出错误)。 此外,您可以使用_DEBUG
或_RELEASE
config.xml中的变量进行后缀,并且它将根据需要使用这些值。
它假定以下项目结构:
/
cordova
config.xml
.env
(包含您的环境变量) build
(构建目录和cordova应用程序的最终输出) 我已经实现了创建模板config.xml
(文件是config.tpl.xml
)和before_prepare
cordova挂钩,用正确的值替换模板中的变量,并将生成的内容保存在config.xml
。
cordova钩子使用npm包es6-template-strings
:
npm install es6-template-strings --save-dev
钩子是:
#!/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);
我在src/environments/
目录中有不同环境的文件,这些文件是根据我构建cordova时定义的NODE_ENV
值选择的。 例如,如果NODE_ENV=prod
(production),那么它将使用文件environment.prod.json
:
{
...
"FACEBOOK_APP_ID": "11111111",
"FACEBOOK_APP_NAME": "My Facebook App Name",
...
"PUSH_SENDER_ID": "22222222",
...
}
当钩子被执行时,这部分在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>
变得像:
<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>
只是有一点,你需要添加自动科尔多瓦更改config.xml
的模板(如添加一个插件),但要好得多(和,在我的情况,那么频繁)不是各自之前改变变量尽管不是理想的,但是在不同环境下构建并且更不容易出错。
现在,当我添加/删除插件时,xml模板文件也会更新。 我刚刚添加了这里描述的钩子。
正如您在帖子中提到的,在官方的cordova文档中没有太多关于此的文档。 花了一些时间进行分析后,我得出结论:
现成的一些最小帮助可用于参数化config.xml
可用的插件变量。 这可以通过官方cordova链接中提到的偏好变量来实现。 但这种方法的问题在于它的工作取决于插件的编码方式。
我用facebook插件尝试了这种方法,但它没有用:(我试过如下:
<preference name="MY_CUSTOM_STRING" default="12345678901234567" />
<plugin name="cordova-plugin-facebook4" spec="~1.7.1">
<variable name="APP_ID">$MY_CUSTOM_STRING</variable>
<variable name="APP_NAME" value="My_Appy_App"/>
</plugin>
试过谷歌地图插件的相同方法,它工作:)我尝试如下:
<preference name="MY_CUSTOM_STRING" default="12345678901234567" />
<plugin name="cordova-plugin-googlemaps" spec="~1.3.9">
<variable name="API_KEY_FOR_ANDROID">$MY_CUSTOM_STRING</variable>
</plugin>
所以我可以得出结论,参数化方法依赖于核心插件代码。
在facebook插件的情况下,如果你想参数化APP_ID
变量,那么我猜钩子是继续进行的方式。 即使是一个简单的Windows批处理文件来替换字符串匹配也应该没问题,并且可以在预构建操作上调用它来实现您的需求。 希望能帮助到你。
更新:
我同意布兰登的评论。
由于时间有限,我能够拿出解决这个问题的cordova钩子。 它可能是粗糙的方式,它也可以改进,但现在这种方法工作正常。 已经将钩子作为示例应用程序发布在我的github页面中 ,并且README文件包含有关它的完整信息。 希望能帮助到你。 让我发布。
在我的实践中,我们只是将两个文件命名为config.xml
和config.beta.xml
来分隔变量。
如果构建beta版apk,请在cordova platform add xxx
之前运行shell mv config.beta.xml
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.