【问题标题】:Build angular app with multiple environments and multiple flavours构建具有多种环境和多种风格的 Angular 应用程序
【发布时间】:2019-08-01 19:29:44
【问题描述】:

我们的产品包含一个 Angular 网络应用程序,该应用程序使用 Firebase 和多个客户。每个客户都有自己的 Firebase 实例(开发和产品)。 Firebase 用于托管网络应用,该应用需要 Firebase 凭据才能访问 Firestore、Auth 和 Cloud Storage。

我们希望以这样一种方式设置 angular.json,以便在部署到新客户端时,我们必须添加尽可能少的行来选择正确的 Firebase 配置。

使用fileReplacements 选项拥有多个环境并不难,但我不知道如何在它们之间共享配置,因此我们不必将 prod 和 dev 特定配置放在所有客户中。

我认为我们可以构建一个自定义 CLI 构建器来交换配置文件,但对于如此简单的事情来说,这似乎是一项艰巨的任务。所有客户共享相同的代码库。

我在构建工具方面的经验有限,我希望我错过了一种简单的方法来实现这一点。

提前致谢!

【问题讨论】:

  • 您要部署到 Firebase 托管吗?
  • 您检查过配置中的fileReplacements 选项吗?
  • 问题已更新! @DougStevenson 托管、身份验证、Firestore 和云存储。 Pierre,我看到了如何创建多个环境,我没有看到的是如何重用 prod 和 dev 配置,因此我不必无休止地重复它们。
  • 如果这有助于您在启动时加载 json 文件并使用它们来配置您的应用程序。
  • 但是如何在不使用 URL 或类似技巧的情况下选择正确的配置?我可以创建一个 bash 脚本或其他任何东西,但我想知道是否有使用 angular 或 firebase 工具的优雅解决方案。

标签: angular firebase angular-cli firebase-hosting


【解决方案1】:

由于您使用的是 Firebase 托管,因此您可以使用一个特殊的 URL,该 URL 将为您提供项目的特定配置。这在documentation 中有描述。具体来说,第二个在SDK auto-configuration。如果您从网页中加载以下相对 URL,例如此脚本,则包括:

<script src="/__/firebase/init.js"></script>

它将为项目提供默认配置并初始化 Firebase SDK。如果您不想使用脚本包含,也可以动态加载此脚本。

如果您这样做,您还必须使用 Firebase 托管模拟器在本地测试您的网站,因为它会正确解释当前项目的特殊 URL。

【讨论】:

  • 我不明白如何为customerA和customerB放置特定的init.js,你能详细说明一下吗?
【解决方案2】:

由于 2019 年 8 月 angular-cli 不支持多维环境。我最终编写了自己的简单节点脚本来服务和构建。

脚本将environments/{projectId}.ts 复制到environments/environment.ts 并启动ng build|serve。我删除了 angular.json 中的 production:fileReplacements 所以 --prod 模式不会替换文件。

现在,当新客户到来时,我只需在具有 firebase 凭据和其他自定义变量的环境中创建 projectId.*.ts 文件。

对于开发,我使用node build-cli.js serve customer-dev -o,对于构建,我使用node build-cli.js build customer-prod --prod

build-cli.js

const fs = require('fs');
const path = require('path');

const argv = require('yargs').demandCommand(2).argv;

// You can make the script self-explainable very easy with yargs,
// highly recommended if you are in a team!

const command = argv._[0];
const projectId = argv._[1];

// Absolute path of environments
const pathOrigen = path.join(__dirname, 'src', 'environments', projectId + '.ts');
const pathDestino = path.join(__dirname, 'src', 'environments', 'environment.ts');

// Test file exists and so...

try {
  fs.copyFileSync(pathOrigen, pathDestino);
} catch (error) {
  console.error(error);
  process.exit(0);
}


// Collect options for ng (-o and --prod).
const options = [command];
if (argv.o) {
  options.push('-o');
  if (command === 'build') {
    console.error('Errror: build and -o are not compatible.\n\n');
    yargs.showHelp('log');
    process.exit(0);
  }
}
if (argv.prod) {
  options.push('--prod');
}
// Launch ng with selected options
let childRunning = true;
console.log('Launching ng ' + options.join(' '));
const child = require('child_process').spawn(
  'ng',
  options, {
    stdio: 'inherit'
  }
);

// If child dies we exit
child.on('close', (code) => {
  childRunning = false;
  process.exit(0);
});

// If we exit we kill the child
process.on('exit', function() {
  if (childRunning) {
    child.kill();
  }
});

【讨论】:

    猜你喜欢
    • 2015-05-15
    • 2019-11-15
    • 1970-01-01
    • 2015-07-07
    • 2016-09-24
    • 1970-01-01
    • 2022-01-11
    • 1970-01-01
    • 2020-10-25
    相关资源
    最近更新 更多