Как создавать сборки, ориентированные на несколько сред

Обновление: в create-react-app 1.0.0 добавлена ​​встроенная поддержка файлов конфигурации, ориентированных на три предопределенных среды (development, test и production), а в 1.1.0 дополнительно добавлена ​​поддержка расширения переменных. Я добавил раздел в конец этой статьи (см .: Встроенная поддержка), в котором описываются изменения и ограничения.

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

Переменные среды

React импортирует переменные среды, которые определены в файле .env в корне проекта. Перейдите к Конфигурация среды, если вы уже знакомы с деталями, но помните, что значения в .env действуют как значения по умолчанию.

Обзор

  • Переменные можно определить в вашей оболочке или в файле .env в корне проекта.
  • Импортируются только переменные, начинающиеся с REACT_APP_.
  • Импортированные значения помещаются в process.env, например process.env.REACT_APP_SECRET_CODE.
  • Чтобы увидеть новые / обновленные переменные, необходимо перезапустить сервер разработки.
  • Переменные из оболочки имеют приоритет над переменными в файле .env.
  • ЗначениеNODE_ENV автоматически устанавливается на разработка (при использовании npm start), тест (при использовании npm test) или производство (при использовании npm build). Таким образом, с точки зрения create-react-app существует всего три среды.

Установка значений

Переменные можно определять до или во время работы npm start или npm build:

$ REACT_APP_SECRET_CODE=dev123 npm start
$ REACT_APP_SECRET_CODE=prod456 npm build

Значения можно установить в package.json и, следовательно, отслеживать в системе контроля версий:

"scripts": {
  "start": "REACT_APP_SECRET_CODE=123 react-scripts start",
  ...
}

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

Значения в .env автоматически импортируются сервером разработки и процессом сборки. Формат такой же, как в оболочке (name=value), с переменной на строку:

$ cat .env
REACT_APP_SECRET_CODE=123
REACT_APP_HOST_ENV=staging
$

Преимущества помещения определений в .env включают:

  • Легко читать по мере роста конфигурации.
  • Легче автоматизировать (подробнее об этом ниже).
  • Значения в файле действуют как значения по умолчанию и могут быть переопределены одним из описанных выше методов (определяемых в оболочке). Таким образом, другие могут переопределять переменные локально, не изменяя .env. Описанная ниже установка с несколькими средами воспользуется этим преимуществом.

Приложение Create React использует dotenv для обработки конфигурации. См. Документацию dotenv, чтобы узнать больше о его синтаксисе и семантике.

Использование значений

Импортированные значения автоматически помещаются в process.env. Их не нужно импортировать вручную. Импортированные значения можно использовать так же, как те, которые определены в ваших файлах JS:

if (process.env.NODE_ENV === 'production') { ... }
app.listen(process.env.REACT_APP_PORT);

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

Конфигурация среды

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

Обзор

  • Определите переменные (со значениями по умолчанию или без них) в .env.
  • Поместите специфичные для среды значения / переопределения в файл .env.local в расположение сборки для целевой среды.
  • При необходимости создайте файлы .env для конкретной среды (например, .env.staging) и используйте их в процессе сборки.

Определить переменные в .env

Переменные могут быть установлены вне приложения create-react-app (например, в сценарии запуска оболочки), но для обеспечения согласованности, воспроизводимости и уменьшения загадочности мы должны вместо этого выбрать метод, который можно универсально использовать в каждой среде. - от местной разработки до производства. Это помогает гарантировать, что большая часть команды сможет эффективно помочь в поддержке среды, когда возникнет необходимость. Другими словами, мы хотим использовать метод, который лучше всего создает процесс, в котором:

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

В настоящее время это можно сделать в приложении create-react-app с помощью файлов .env.

Шаг 1, таким образом, заключается в создании файла .env для вашего проекта, если у вас его еще нет, разместить в нем свою конфигурацию и обновить ссылки на конфигурацию в вашем коде. На данный момент мы предполагаем, что это ваши ценности развития, но мы скоро вернемся к этому.

Также стоит отметить, что при использовании файлов .env переменные не являются глобальными для среды и не сохраняются после выполнения команды start. На мой взгляд, это хорошо. Однако create-response-app еще не поддерживает dotenv-expand, поэтому для некоторых настроек это может быть недостатком (update: с 1.1.0 он поддерживает расширение).

Значения, специфичные для среды в .env.local

Dotenv (то, что сценарии реакции используют для импорта переменных среды) также проверяет наличие файла с именем .env.local и, если он присутствует, также импортирует переменные, определенные в нем. В случае, если в обоих файлах определено одно и то же значение, порядок приоритета (сначала наивысший):

  • Оболочка
  • .env.local
  • .env

Таким образом, значения в .env.local переопределяют значения в .env.

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

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

Наконец, запись для .env.local должна быть добавлена ​​в список игнорирования системы контроля версий (например, .gitignore), поскольку она не должна проверяться. Если вы публикуете модуль с файл .npmignore, он также должен быть добавлен туда.

Файлы .env для конкретной среды

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

Один из способов решить эту проблему - создать файлы .env для каждой среды (например, .env.staging вместо .env.local) и отслеживать эти файлы в системе контроля версий. В этом случае dotenv не будет автоматически импортировать файлы, но сценарий сборки в package.json можно изменить, чтобы он выполнял это вместо этого (update: с 1.0.0 это шаг не требуется для трех предопределенных сред - файлы импортируются автоматически):

"scripts": {
  "build": "sh -ac '. .env.build; react-scripts build'",
  ...
}

Команда . аналогична команде source. Это означает выполнение файла в текущем контексте. В этом случае переменные среды внутри будут определены перед запуском следующей команды: react-scripts build. Он имеет тот же порядок приоритета, что и при использовании .env.local.

Для нескольких сред сборки описанный выше метод можно обобщить:

"scripts": {
  "build": "sh -ac '. .env.${REACT_APP_ENV}; react-scripts build'",
  ...
}

Теперь любой, у кого есть доступ к соответствующей конфигурации, может выполнить сборку для этой среды, указав REACT_APP_ENV во время сборки:

$ REACT_APP_ENV=staging npm run build

Для каждой среды можно добавить дополнительные ярлыки:

"scripts": {
  "build": "sh -ac '. .env.${REACT_APP_ENV}; react-scripts build'",
  "build:staging": "REACT_APP_ENV=staging npm run build",
  "build:production": "REACT_APP_ENV=production npm run build",
  ...
}

Сокращение команды сборки до:

$ npm run build:staging

Управление конфигурацией в системе контроля версий

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

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

Модуль NPM

Как указал Фрэнсис Родригес, react-app-env - это модуль, который автоматизирует большую часть того, что здесь описано, и может быть подходящим для ваших нужд. Чтобы использовать response-app-env:

Установите его как зависимость разработчика:

$ yarn add --dev react-app-env (or npm install --save-dev)

И изменим скрипты запуска и сборки:

"scripts": {
  "start": "react-app-env start'",
  "build": "react-app-env build'",
  "test": "react-app-env test'",
  ...
}

И, наконец, добавьте как минимум два файла конфигурации: development.env и production.env. В отличие от шагов выше, response-app-env автоматически добавляет REACT_APP_ к переменным. Таким образом, определения переменных в приведенном выше примере будут изменены на:

SECRET_CODE=123
HOST_ENV=staging

Однако в приложении для ссылки на переменную по-прежнему должно использоваться полное имя, включая REACT_APP_. Учитывая это, я лично предпочел бы, чтобы библиотека не добавлялась автоматически, чтобы предотвратить недоразумения, но я не вижу для этого варианта.

По умолчанию development.env используется импортированным в npm start и npm test, а production.env в npm build. Флаг --env-file может использоваться для поддержки большего количества сред:

"scripts": {
  "build:staging": "react-app-env --env-file=staging.env",
  ...
}

Содержимое .env все еще можно использовать в качестве значений по умолчанию, но REACT_APP_ не добавляется автоматически к переменным в этом файле.

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

"scripts": {
    "build": "react-app-env --env-file=config/${BUILD_ENV}.env build",
  "build:staging": "BUILD_ENV=staging npm run build",
  "build:production": "BUILD_ENV=production npm run build",
  ...
}

Основные различия между этим подходом, описанным выше (который не использует response-app-env), - это автоматическое добавление REACT_APP_ и, возможно, лучшая кроссплатформенная поддержка.

Встроенная поддержка

В Create-react-app 1.0.0 добавлена ​​поддержка автоматического чтения файлов конфигурации для трех предопределенных сред: development, test и production.

Как и раньше, значения по умолчанию (самый низкий приоритет) могут быть определены в .env, а значение NODE_ENV устанавливается автоматически в зависимости от используемого скрипта:

  • старт → разработка
  • тест → тест
  • сборка → производство

В выпуске 1.0.0 добавлена ​​встроенная поддержка файла конфигурации, соответствующего каждому из них: .env.development, .env.test и .env. .production. Значения из этих файлов имеют более высокий приоритет, чем значения в .env. Каждый файл (включая файл по умолчанию) поддерживает другой уровень переопределений, добавляя .local в конец. Полный порядок приоритета (сначала самый высокий):

  1. оболочка
  2. .env. {среда} .local
  3. .env. {среда}
  4. .env.local
  5. .env

Поддержка dotenv-expand была добавлена ​​в 1.1.0, что позволяет расширять переменные в файлах .env (пример из документации create-response-app):

DOMAIN=www.example.com
REACT_APP_FOO=$DOMAIN/foo
REACT_APP_BAR=$DOMAIN/bar

Расширение переменных работает с переменными, определенными локально (в том же файле) или в оболочке, но, к сожалению, не работает для файлов. Например, значение, определенное в .env, нельзя раскрыть в .env.development.