【问题标题】:Using environment variables / parameterizing config.xml使用环境变量/参数化 config.xml
【发布时间】:2016-10-15 10:09:46
【问题描述】:

我正在使用 cordova-plugin-facebook4 插件构建一个 ionic/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 用于开发应用程序,我们有一个单独的 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 文档中没有看到任何允许您执行此操作的内容。

【问题讨论】:

  • hooks 呢?
  • Hooks 和/或构建脚本(手动、通过 grunt、通过 gulp 等)可能是去这里的唯一方法,但我留下了赏金,看看是否有人能想出一个在科尔多瓦范围内更聪明的解决方案。

标签: javascript android facebook cordova ionic-framework


【解决方案1】:

正如您在帖子中提到的,cordova 官方文档中没有太多关于此的文档。在花了一些时间进行分析后,我得出以下结论:

config.xml 中提供了一些现成的最小帮助来参数化插件变量。这可以通过official cordova link 中提到的偏好变量来实现。但是这种方法的问题在于它的工作方式取决于插件的编码方式。

我用 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 批处理文件来替换字符串匹配也应该没问题,并且可以在预构建操作中调用它来实现您所需要的。希望对您有所帮助。

更新:

我同意 Brandon 的 cmets。

在有限的时间里,我想出了解决这个问题的科尔多瓦钩子。这可能是一种粗略的方法,也可以改进,但目前这种方法效果很好。已在我的github page 中将钩子作为示例应用程序发布,并且 README 文件包含有关它的完整信息。希望能帮助到你。随时通知我。

【讨论】:

  • 你能解释一下在这种情况下如何使用钩子吗?
  • 我认为&lt;preference&gt; 方法的问题之一是它仍然需要在config.xml 中定义变量,只是在与&lt;plugin&gt; 的@987654330 不同的地方@。问题是寻求一种方法,允许在构建时提供这些变量的值,而不是在(可能的)版本控制文件中,例如 config.xml
  • @Brandon 感谢 cmets。已发布更新答案。希望对您有所帮助。
  • @ExplosionPills 已为您发布了工作挂钩。感谢您让我有机会尝试我的第一个 Cordova 钩子 :)
【解决方案2】:

@Ghandi 的使用cordova hooks 的解决方案是一个很好的例子,说明了如何实现这一点,尽管它只针对windows,因为它使用批处理文件和PowerShell 作为hook 脚本。

作为跨平台解决方案,您可以在 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 中以两个美元符号开头并由字母数字字符和下划线组成的任何变量,如果它存在则使用相应环境变量的值(如果不存在则抛出错误)。此外,您可以在 config.xml 中为变量添加后缀 _DEBUG_RELEASE,它会酌情使用这些值。

它假定以下项目结构:

  • /
    • cordova
      • config.xml
      • ...(您的 cordova 安装的其余部分)
      • .env(包含你的环境变量)
    • build(cordova 应用的构建目录和最终输出)

【讨论】:

  • 感谢您发布其他方式来完成此操作。有用的信息。快乐编码。干杯
【解决方案3】:

我已经实现了创建一个模板config.xml(文件是config.tpl.xml)和一个before_preparecordova 挂钩来用正确的值替换模板中的变量并将生成的内容保存在config.xml 中。

cordova hook 使用 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(生产),那么它将使用文件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 的自动cordova 更改(例如添加插件),但这比必须更改每次构建之前的变量都使用不同的环境,而且更不容易出错,尽管这并不理想。

更新 (2017-10-13)

现在,当我添加/删除插件时,xml 模板文件也会更新。我刚刚添加了here 描述的钩子。

【讨论】:

    【解决方案4】:

    在我的实践中,我们只是将两个文件名 config.xmlconfig.beta.xml 放在单独的变量中。

    如果构建测试版 apk,请在 cordova platform add xxx 之前运行 shell mv config.beta.xml

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-08
      • 2023-03-30
      • 2016-01-22
      • 2019-08-24
      • 1970-01-01
      • 2023-02-02
      相关资源
      最近更新 更多