简体   繁体   English

构建具有多种环境和多种风格的 Angular 应用程序

[英]Build angular app with multiple environments and multiple flavours

We have a product that includes an Angular web app that uses Firebase with multiple costumers.我们有一个产品,其中包含一个 Angular 网络应用程序,该应用程序将 Firebase 与多个客户一起使用。 Each costumer has its own Firebase instances (dev and prod).每个客户都有自己的 Firebase 实例(开发和生产)。 Firebase is used for hosting the web app and the app needs Firebase credentials for accessing Firestore, Auth and Cloud Storage. Firebase 用于托管 Web 应用程序,该应用程序需要 Firebase 凭据才能访问 Firestore、Auth 和 Cloud Storage。

We would like to setup angular.json in such a way that when deploying to a new client we have to add the minimum posible of lines to pick the correct Firebase configuration.我们希望以这样的方式设置 angular.json,以便在部署到新客户端时,我们必须添加最少可能的行以选择正确的 Firebase 配置。

It is not difficult to have multiple environments using fileReplacements options, but I don't see how to share configs between them, so we don't have to put prod and dev specific configs in all customers.使用fileReplacements选项拥有多个环境并不困难,但我不知道如何在它们之间共享配置,因此我们不必在所有客户中放置特定于生产和开发的配置。

I think we could build a custom CLI builder that swaps config files, but that seems a huge task for something so simple.我认为我们可以构建一个自定义 CLI 构建器来交换配置文件,但这对于如此简单的事情来说似乎是一项艰巨的任务。 All customers share the same code base.所有客户共享相同的代码库。

My experience with build tools is limited, I hope I am missing an easy way to accomplish this.我在构建工具方面的经验有限,我希望我错过了一种简单的方法来实现这一点。

Thanks in advance!提前致谢!

Since you're using Firebase Hosting, there is a special URL you can use that will give you your project's specific configuration.由于您使用的是 Firebase 托管,因此您可以使用一个特殊的 URL,该 URL 将为您提供项目的特定配置。 This is described in the documentation .这在文档中有所描述。 Specifically, the second on SDK auto-configuration .具体来说,第二个关于SDK 自动配置 If you load the following relative URL from your web pages like this script include:如果您从您的网页中加载以下相对 URL,例如此脚本,请包括:

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

It will provide the default configuration for the project and initialize the Firebase SDK.它将为项目提供默认配置并初始化 Firebase SDK。 You can also load this script dynamically if you don't want to use a script include.如果您不想使用脚本包含,也可以动态加载此脚本。

If you do this, you will also have to test your web site locally with the Firebase Hosting emulator, as it will correctly interpret the special URL for the current project.如果您这样做,您还必须使用 Firebase 托管模拟器在本地测试您的网站,因为它会正确解释当前项目的特殊 URL。

As August 2019 angular-cli does not support multi-dimension environment.由于 2019 年 8 月 angular-cli 不支持多维环境。 I ended writing up my own simple node script for serving and building.我最终编写了自己的用于服务和构建的简单节点脚本。

The script copies environments/{projectId}.ts to environments/environment.ts and launches ng build|serve.该脚本将环境/{projectId}.ts 复制到环境/环境.ts 并启动 ng build|serve。 I removed production:fileReplacements in angular.json so --prod mode does not replace the file.我删除了 angular.json 中的 production:fileReplacements 所以 --prod 模式不会替换文件。

Now, when and new costumer arrives I only have to create projectId.*.ts files in environments with firebase credentials and other custom variables.现在,当新客户到来时,我只需要在具有 firebase 凭据和其他自定义变量的环境中创建 projectId.*.ts 文件。

For developing I use node build-cli.js serve customer-dev -o and for building node build-cli.js build customer-prod --prod .对于开发,我使用node build-cli.js serve customer-dev -o和用于构建node build-cli.js build customer-prod --prod

build-cli.js构建 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();
  }
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM