Angular Azure 插槽部署存在 2 个配置问题

Angular 2 configuration issues with Azure Slot deployments

我在使用 Angular 环境变量和 Azure Slots

时遇到问题

我们想使用提供静态 Angular 文件的应用服务,我们还想使用 Azure 插槽来使我们的部署更安全。

我们要使用插槽的原因是:

  1. 确保代码在生产环境中正常工作,然后才能完全供所有人使用
  2. 将停机时间减少到几乎为零,因为在 "go-live" 阶段没有部署构建

我们的 Angular 站点仅提供静态文件,这意味着插槽部署需要不同的构建来为每个插槽填充不同的 env.json 环境设置。

我们正在考虑采用的解决方案是在同一个 Angular 网站中创建一个端点,然后从 Angular 站点调用返回其源以获取其配置。通过这种方式,可以在 Azure 的暂存和生产槽中设置不同的配置,并且只需要一个 Angular 构建。

我们需要一些服务器端代码来获取这些 Azure 应用程序设置并在站点的端点中提供它们。我们尚未就用于创建该端点的技术做出决定 - 我们目前正在考虑 .Net Core 或 NodeJs,因为它们似乎非常适合 Angular 产品和开发团队。

有没有人有插入服务器端组件为以前静态的 Angular 网站提供配置的经验?

为了达到您的要求,您只需将以下 PHP 文件放入您的站点根文件夹即可。然后通过您的 Angular 应用向端点 http://<websitename>.azurewebsites.net/appSettings.php 发送 GET 请求。这将为您提供一个 JSON 对象,其中包含所有 应用程序设置

appSettings.php

<?php

$appSettings = [];

foreach ($_SERVER as $key => $value) {

    if(preg_match('/^APPSETTING_/', $key)) {
        $appSettings[str_replace('APPSETTING_', '', $key)] = $value;
    }
}

header('Content-Type: application/json');
echo json_encode($appSettings);

也许有人还需要它。我建议更接近所选技术并公开 node.js api 类似于之前的 php 答案。

我创建在 Azure AppService 中公开的端点 http://<websitename>.azurewebsites.net/app-settings,如下所示:

将 index.js 文件添加到 Angular 代码中的 src 目录中:

var http = require('http');
var server = http.createServer(function (request, response) {
    response.writeHead(200, { "Content-Type": "application/json" });
    var result = {};
    result.someAppSetting = process.env.SomeApplicationSetting;
    var jsonResult = JSON.stringify(result);
    response.end(jsonResult);
});
var port = process.env.PORT || 1337;
server.listen(port);
console.log("Server exposing api for reading application settings running at http://localhost:%d", port);

因此,响应包含 json 以及 process.env.SomeApplicationSetting 从环境变量中检索到的 SomeApplicationSetting 应用程序设置。当然,您可以采用其他策略来公开变量,例如仅向 json 或任何其他内容添加一些前缀设置。

将 index.js 添加到 angular.json 中的资产:

"assets": [
  "src/favicon.ico",
  "src/assets",
  "src/web.config",
  "src/index.js"
],

然后在web.config中添加如下重写规则:

<rule name="Read app settings" stopProcessing="true">
  <match url="app-settings" />
  <action type="Rewrite" url="index.js"/>
</rule>

我查看了所有解决方案并创建了一个在 Azure 和本地计算机 (localhost) 上运行的解决方案。这取决于构建 - prod(从 Azure 读取)或 dev(从本地资产文件夹读取)Azure 插槽。

也许对某人有帮助。

首先,您需要像 Aaron Chen 提到的那样添加这个小 php 文件。 在 src 文件夹下的 Angular 结构中:

src/appSettings.php

$appSettings = [];

foreach ($_SERVER as $key => $value) {

    if(preg_match('/^APPSETTING_/', $key)) {
        $appSettings[str_replace('APPSETTING_', '', $key)] = $value;
    }
}

header('Content-Type: application/json');
echo json_encode($appSettings, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);

需要修改angular.json文件。您需要将 assets 添加到 "src/appSettings.php"

        "assets": [
          "src/favicon.ico",
          "src/assets",
          "src/appSettings.php"
        ],

此解决方案从 http://<websitename>.azurewebsites.net/appSettings.php link 中的 azure 获取所有配置。 这仅适用于 Azure(需要身份验证)。对于本地开发,您需要创建一个 Json 文件 包含 src/assets 文件夹下的所有 Azure 插槽。

`assets/config/backend.json`;

要加载配置 Json 需要创建

src/app/app.config.ts

import { Injectable } from '@angular/core';
import { HttpClient, HttpBackend  } from '@angular/common/http';
import { AppSettings } from './models/AppSettings.model';
import { environment } from 'src/environments/environment';

@Injectable()
export class AppConfig {
    static appSettings: AppSettings;

    private http: HttpClient;
    constructor( handler: HttpBackend) {
        this.http = new HttpClient(handler);
    }

    public load() {
        let backendConfigUrl: string;
        if (environment.production) {
            backendConfigUrl = window.location.origin + '/appsettings.php';
        } else {
            backendConfigUrl = `assets/config/backend.json`;
        }
        console.log(backendConfigUrl);

        return new Promise<void>((resolve, reject) => {
            this.http.get<AppSettings>(backendConfigUrl).toPromise().then((response: AppSettings) => {
                AppConfig.appSettings = response;
                resolve();
            }).catch((response: any) => {
               reject(`Could not load file ${backendConfigUrl}: ${JSON.stringify(response)}`);
            });
        });
    }
}

然后修改src/app/app.module.ts在应用启动前加载配置

export function initializeApp(appConfig: AppConfig) {
  return () => appConfig.load().then(() => {
    console.log(AppConfig.appSettings)
  });
}

 providers: [
    AppConfig,
    {
      provide: APP_INITIALIZER,
      useFactory: initializeApp,
      deps: [AppConfig],
      multi: true
    },
  ]

To ng build 从本地 assets 文件夹加载配置。 To ng build --prod 从 Azure 读取配置。与 ng serveng serve --prod

相同