Допустим, у нашего приложения есть 3 среды — разработка, подготовка и производство. У нас могут быть разные конфигурации для каждой из этих сред, таких как серверные конечные точки, ключи API аналитики, ключи API отчетов об ошибках, настройки, такие как отключение журналов отладки в производственной среде и т. д.

Существует три распространенных способа управления этими конфигурациями:

1. Внедрение во время сборки. Для каждой среды создайте отдельный пакет и внедрите конфигурацию, специфичную для среды, в код.

2. Разрешение среды выполнения. Храните конфигурации для всех сред в одном пакете и динамически разрешайте нужную конфигурацию во время выполнения.

3. Удаленная загрузка — получение конфигурации из серверной части во время выполнения.

Поговорим о каждом из этих подходов, их плюсах и минусах.

Внедрение во время сборки

Приложения SPA обычно создаются с помощью сборщика и развертываются на веб-серверах или копируются в образ докера nginx и развертываются на контейнерных платформах.

При таком подходе для каждой среды создается отдельный пакет (или образ докера), а значения конфигурации для этой среды вводятся в пакет с использованием «переменных среды». Конечно, во внешнем интерфейсе нет такой вещи, как переменные среды, поэтому обычно это имитируется с помощью глобальных переменных.

Если вы используете webpack, create-react-app или vue-cli и т. д., вы можете получить доступ к значению конфигурации как process.env.YOUR_CONFIG_NAME и т. д.

Недостатки:

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

- Способ доступа к конфигурации кажется хакерским — вам нужно получить его из объекта process.env, который не является частью API браузера.

- Вы не можете использовать это, если вы не используете упаковщик или инструмент сборки.

- Поскольку значения конфигурации будут вводиться из CI/CD, они, скорее всего, не будут контролироваться версиями.

Преимущества:

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

Разрешение во время выполнения

В качестве альтернативы мы можем хранить конфигурации для всех сред в исходном коде и динамически загружать соответствующую конфигурацию для каждой среды. Обычно разные среды имеют разные URL-адреса, и мы можем использовать это для загрузки правильной конфигурации.

Допустим, у нас есть 3 среды — разработка, подготовка и производство, которые имеют следующие URL-адреса — dev.myapp.com, staging.myapp.com и www.myapp.com соответственно.

Конфигурации для этих трех сред можно хранить в dev.config.json, staging.config.json и prod.config.json.

// dev.config.json
{
  "API_URL": "dev.myapp.com/api",
  "ANALYTICS_KEY": "xxxaaa",
  "ERROR_REPORTING_KEY": "xxxeee",
  "IS_LOGGING_ENABLED": true
}
// staging.config.json
{
  "API_URL": "staging.myapp.com/api",
  "ANALYTICS_KEY": "xxxaaa",
  "ERROR_REPORTING_KEY": "xxxeee",
  "IS_LOGGING_ENABLED": true
}
// prod.config.json
{
  "API_URL": "www.myapp.com/api",
  "ANALYTICS_KEY": "yyyaaa",
  "ERROR_REPORTING_KEY": "yyyeee",
  "IS_LOGGING_ENABLED": false
}

Мы можем использовать window.location.hostname, чтобы решить, какую конфигурацию загружать во время выполнения:

// Config.js

import prod from "./prod.config.json";
import staging from "./staging.config.json";
import dev from "./dev.config.json";

let config = {};

switch (window.location.hostname) {
  case "www.myapp.com":
    config = prod;
    break;
  case "staging.myapp.com":
    config = staging;
    break;
  case "dev.myapp.com":
    config = dev;
    break;
  default:
    config = dev;
}

export default config;

Это может быть использовано в приложении как

// ApiClient.js

import axios from "axios";
import Config from "../Config";

const ApiClient = axios.create({ baseURL: Config.API_URL });

export default ApiClient;

Обычно некоторые значения конфигурации повторяются для разных сред. Например, вы можете решить использовать один и тот же ключ API аналитики для всех непроизводственных сред. Мы можем сделать конфиги СУХИМИ, извлекая эти общие значения конфигов в common.config.json

// common.config.json
{
  "ANALYTICS_KEY": "xxxaaa",
  "ERROR_REPORTING_KEY": "xxxeee",
  "IS_LOGGING_ENABLED": true
}
// dev.config.json
{
  "API_URL": "dev.myapp.com/api"
}
// staging.config.json
{
  "API_URL": "staging.myapp.com/api"
}
// prod.config.json
{
  "API_URL": "www.myapp.com/api",
  "ANALYTICS_KEY": "yyyaaa",
  "ERROR_REPORTING_KEY": "yyyeee",
  "IS_LOGGING_ENABLED": false
}

конфиги можно объединить в Config.js

// Config.js

import common from "./common.config.json";
import prod from "./prod.config.json";
import staging from "./staging.config.json";
import dev from "./dev.config.json";

let config = {};

switch (window.location.hostname) {
  case "www.myapp.com":
    config = { ...common, ...prod };
    break;
  case "staging.myapp.com":
    config = { ...common, ...staging };
    break;
  case "dev.myapp.com":
    config = { ...common, ...dev };
    break;
  default:
    config = { ...common, ...dev };
}

export default config;

Преимущества:

- Один и тот же пакет (или образ докера) можно использовать для всех сред.

- Работает для проектов, в которых не используются упаковщики или инструменты сборки.

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

Недостатки:

- Вы раскрываете существование других сред злоумышленникам. Это может быть проблемой, если вы не уверены в безопасности вашей надежной инфры.

Удаленная загрузка

Как правило, сборка внешнего интерфейса не занимает много времени, поэтому легко развернуть изменения конфигурации для пользователей в течение нескольких минут. Но иногда вам может понадобиться изменить конфигурацию из бэкэнда:

- Используйте разные наборы конфигураций для разных сегментов пользователей — A/B-тестирование, поэтапное развертывание, функциональные флаги и т. д.

- Обходные процессы — на некоторых предприятиях приходится выполнять множество процессов, чтобы развернуть одно изменение на производственной площадке. В таких случаях полезно получить некоторые конфигурации из бэкэнда.

Несмотря на эти преимущества, тот факт, что мы извлекаем их из серверной части, усложняет ситуацию — нам нужно проектировать код/интерфейс с учетом задержки и реализовать кэширование таким образом, чтобы оно не подрывало упомянутые выше преимущества. Этот подход обычно используется вместе с любым из первых двух подходов.

Спасибо за чтение! :)

Первоначально опубликовано на sheshbabu.com