【问题标题】:Angular (8) application build once (with production config) and deploy to multiple environmentsAngular (8) 应用程序构建一次(使用生产配置)并部署到多个环境
【发布时间】:2020-05-13 05:18:52
【问题描述】:

我有一种情况,我正在尝试使用生产配置构建我的 Angular 应用程序并部署到多个环境,例如,ng build --configuration=production

这里的工作流程是当我使用上述命令(ng build --configuration=production)进行构建时,environment.ts 文件被替换为 environment.prod.ts

我在environment.prod.ts中的配置如下,

export const environment = {
  production: true,
  environment: 'Production',
  _webApiHost: 'prodsomename.company.com/api/',
};

我在environmrnt.test.ts中的配置如下,

export const environment = {
    production: true,
    environment: 'Test',
    _webApiHost: 'testsomename.company.com/api/',
};

我对 angular.json 文件的设置如下,

"configurations": {
            "production": {
              "fileReplacements": [ {
                "replace": "src/environments/environment.ts",
                "with": "src/environments/environment.prod.ts"
              } ],
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": false,
              "extractCss": true,
              "namedChunks": false,
              "aot": true,
              "extractLicenses": true,
              "vendorChunk": false,
              "buildOptimizer": true,
              "budgets": [ {
                "type": "initial",
                "maximumWarning": "2mb",
                "maximumError": "5mb"
              } ]
            },
            "test": {
              "fileReplacements": [ {
                "replace": "src/assets/configs/environment.ts",
                "with": "src/assets/configs/environment.test.ts"
              } ],
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": false,
              "extractCss": true,
              "namedChunks": false,
              "aot": true,
              "extractLicenses": true,
              "vendorChunk": false,
              "buildOptimizer": true,
              "budgets": [ {
                "type": "initial",
                "maximumWarning": "2mb",
                "maximumError": "5mb"
              } ]
            }
          }

如果我分别为每个环境构建解决方案并部署到适当的环境,如下图,

它的作用就像魅力,这意味着,

testApp 与 _webApiHost 通信:testsomename.company.com/api/prodApp 与 _webApiHost 通信:prodsomename.company.com/api/

在上述情况下,由 QA 测试的 工件与部署到生产环境的工件不同,这不是将代码推送到生产环境的理想方式。

但我担心的是我只想构建应用程序并将其部署到多个环境中,每个环境都会与适当的 api 进行通信,如下图所示,

当我使用命令 ng build --configuration=production 构建它时,environment.ts 文件将具有生产配置,

export const environment = {
  production: true,
  environment: 'Production',
  _webApiHost: 'prodsomename.company.com/api/',
};

因此,如果将该工件部署到测试环境, testApp 正在尝试与 _webApiHost: 'prodsomename.company.com/api/ 通信,这是不对的。

这是我用来构建解决方案的 Azure DevOps 构建管道 powershell 脚本。

Set-Location "$(Build.Repository.LocalPath)\Buffini.Web.UI\Angular"
Write-Host 'Angular Install Starting'
npm install -g @angular/cli@8.0.6 -Verbose
Write-Host 'Angular Install Finished'
Write-Host 'NPM Install Starting'
npm install -Verbose
Write-Host 'NPM Install Finished'
Write-Host 'NPM Update Starting'
npm update -Verbose
Write-Host 'NPM Update Finished'
Write-Host 'NPM Audit Starting'
npm audit fix -Verbose
Write-Host 'NPM Audit Finished'
Write-Host 'Angular Build Starting'
ng build --configuration=production --deleteOutputPath=true
Write-Host 'Angular Build Finished'

我已尝试在线搜索解决方案,但找不到任何解决方案。 请帮助我解决问题。我将非常感谢您的时间和帮助。提前致谢。

【问题讨论】:

    标签: azure-devops angular8 azure-pipelines-release-pipeline build-pipeline


    【解决方案1】:

    在运行时替换应用配置。您需要创建包含动态配置的 config.json 文件(例如_webApiHost)。您可以查看this blog 中的示例代码以获取 config.json。

    在您的管道中,您可以添加扩展任务来替换 config.json 内容,然后再部署到不同的环境(例如测试、生产)。

    这样你只需要构建你的 Angular 应用程序一次,并且只需要在部署到不同的环境之前相应地替换 config.json 内容。

    您可以查看可用的扩展程序。 Magic Chunks task,或 RegEx Match & Replace Task。您可以查看this thread 以获取使用这些任务的示例。

    【讨论】:

    • 嗨@Ananth Asamani 您是否尝试过上述扩展,效果如何?
    • 嗨,Levi Lu,很抱歉耽搁了,我被卷入了其他问题,所以不得不解决它们。我最终在我的 service.ts 文件中按照以下方式进行操作,if (window.location.hostname === 'account.company.com') { this._webApiHost = 'api.company.com/api/'; } else if (window.location.hostname === 'test-account.company.com') { this._webApiHost = 'testapi.company.com/api/'; } else { this._webApiHost = 'localhost:62603';这可能不是一个理想或正确的方法,但我现在(暂时)最终有了这个。但现在我正在尝试实施上述您。我会让您知道。
    【解决方案2】:

    我不会假装这是一个答案,但它的想法足够长,不适合 cmets 领域。也许你会发现它很有帮助。 (完全披露:我使用的不是 Azure,而是 GitLab。因此,无论如何,如果您发现这种使用方法,则需要进行一些翻译。)

    不管怎样,我不久前也问过同样的问题。经过一番挖掘,I found this link helpful

    根据该指导,我执行了以下操作:

    首先,我做了一个基本的 docker 构建。在那个版本中,我在一个文件夹中有各种“准备好询问”的环境文件。实际驱动应用的配置文件位于根目录。

    然后我进行另一个 docker 构建,其唯一目的是获取第一个构建并为其提供所需的配置。 (我这样做是因为第一次构建很慢,但我想在不重建的情况下推动生产。)

    接下来我做我想要的环境构建。

    对于暂存,例如:在我的 GitLab 构建 CI/CD 管道 yaml 中,我有这样一行......

    docker build -t xxxxx --build-arg SERVE_CONFIGURATION=staging -f [A-Docker-File] .
    

    docker 文件对于所有环境都是相同的,但根据传入的参数,此 docker 构建会拉取不同的文件并将其猛烈撞击到驾驶员座位上。由于 Angular 部署中没有秘密,因此文件夹结构中潜伏着额外(未使用的)配置文件并不重要(尽管如果有动机,可以轻松删除它们。)

    无论如何,在第二个 docker build 中,我有...

    ...
    FROM registry.gitlab.com/xxxxxxxxxxxx/compiled as default-config
    FROM registry.gitlab.com/xxxxxxxxxxxx/compiled as final-config
    
    COPY --from=default-config /usr/share/nginx/html/environments/environment.$SERVE_CONFIGURATION.js /usr/share/nginx/html/environment.js
    

    所以这个 docker 镜像只不过是之前镜像的构建,但所需的环境文件位于适当的位置。

    无论如何,我可能遗漏了一些细节,但我不确定这是否会对您有所帮助并且会到此为止。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-02
      相关资源
      最近更新 更多