Проблемы конфигурации Angular 2 при развертывании слотов Azure

У меня проблема с переменными среды Angular и слотами Azure

Мы хотим использовать службу приложений, предоставляющую статические файлы Angular, а также хотим использовать слоты Azure, чтобы сделать наши развертывания более безопасными.

Причины, по которым мы хотим использовать слоты:

  1. Убедитесь, что код работает в производственной среде, прежде чем сделать его полностью доступным для всех.
  2. Сократите время простоя почти до нуля, так как сборка не развертывается на этапе запуска.

Наш сайт Angular обслуживает только статические файлы, это означает, что для развертывания слотов требуется другая сборка, чтобы по-разному заполнить настройки среды env.json для каждого слота.

Решение, которое мы думаем принять, - создать конечную точку на том же веб-сайте Angular и позвонить с сайта Angular обратно в его источник, чтобы получить его конфигурацию. Таким образом, конфигурация может быть задана по-разному в промежуточных и производственных слотах в Azure, и потребуется только одна сборка Angular.

Нам нужен код на стороне сервера, чтобы получить эти настройки приложения Azure и вернуть их в конечную точку на сайте. Нам еще предстоит принять решение о технологии, которую мы используем для создания этой конечной точки - на данный момент мы думаем либо о .Net Core, либо о NodeJ, потому что они, похоже, хорошо подходят для продукта Angular и команды разработчиков.

Есть ли у кого-нибудь опыт подключения серверного компонента для настройки ранее статического веб-сайта Angular?


person Tony Sawyer    schedule 09.03.2017    source источник
comment
Это аналогичный вопрос stackoverflow.com/q/42634154/7677661   -  person Tony Sawyer    schedule 09.03.2017


Ответы (3)


Для выполнения ваших требований вы можете просто поместить следующий файл PHP в корневую папку вашего сайта. Затем отправьте запрос GET на конечную точку http://<websitename>.azurewebsites.net/appSettings.php через приложение Angular. Это даст вам объект 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);
person Aaron Chen    schedule 10.03.2017
comment
Большое спасибо! Кстати, в приведенном выше примере отсутствует закрывающий тег (? ›). - person Tony Sawyer; 13.03.2017
comment
Из Руководства по PHP: Желательно опустите закрывающий тег PHP в конце файла, если файл является чистым кодом PHP. Кстати, если мой пост был полезен, примите его как ответ :) - person Aaron Chen; 13.03.2017
comment
Извините, я не эксперт в языке php и предположил, что это ошибка. Я принял ответ, но из-за моей низкой репутации на данный момент некоторые вещи не совсем работают. Когда я получу достаточно, я обязательно дам ему взлет - person Tony Sawyer; 13.03.2017

Может еще кому-то это нужно. Я предлагаю оставаться ближе к выбранной технологии и выставить node.js api аналогично предыдущему ответу php.

Я создаю конечную точку http://<websitename>.azurewebsites.net/app-settings, представленную в Azure AppService, следующим образом:

Добавьте файл index.js в каталог src в коде Angular:

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 с настройкой приложения SomeApplicationSetting, полученной из переменных env пользователем process.env.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>
person szalafe    schedule 29.01.2019

Я просматриваю все решения и создал одно, которое работает как в Azure, так и на локальной машине (localhost). Это зависит от построения - prod (читает из лазурного) или dev (читает из локальной папки ресурсов) слотов лазурного типа.

Может это кому-то поможет.

Сначала вам нужно добавить этот небольшой php-файл, подобный упомянутому Aaron Chen. В структуре Angular в папке src:

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. Это работает только в Azure (требуется проверка подлинности). Для локальной разработки вам необходимо создать файл Json, содержащий все слоты Azure в папке src/assets.

`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 папки. К ng build --prod читает конфиг из Azure. То же, что ng serve и ng serve --prod

person Botond    schedule 24.04.2020