Змінні середовища Vue.js
Olivier Pichon Jan 26 · 6 min read
Змінні середовища в vue.js, звичайно, є критичними, щоб ваш додаток підтримував декілька середовищ (локальне, розробку, постановку, виробництво). Однак вони часто виявляють більше клопоту, ніж того варті. Кожен розробник, кого я знаю, провів декілька годин, намагаючись з'ясувати дивні помилки, пов’язані із завантаженням env vars програми (як правило, рядки, коли очікуєш логічне), а потім ще пару годин, намагаючись розробити остаточне рішення для їх вирішення. Сукупно кількість витрачених людино-годин повинна бути приголомшливою. Ми пропонуємо тут просте рішення для обробки змінних оточуючих середовищ у додатку vue.js. Незабаром ми створимо плагін Vue.
Dotenv: правильний шлях
dotenv
- це фантастичний інструмент для управління вашими env vars
, і вам слід його використовувати. Якщо у вашому додатку використовується vue-cli, він уже включений.
За допомогою dotenv
ви визначаєте оточення у .env
-файлі, збереженому у кореневому каталозі вашого проекту. Цей файл не повинен знаходитись під контролем версій. Ми наполегливо пропонуємо включити .env.example
файл, також у кореневий каталог вашого проекту, який знаходиться під контролем версій, щоб запропонувати обґрунтовані параметри за замовчуванням та вказати, які змінні доступні для використання іншими розробниками. Env vars, визначені в .env
, доступні через process.env.VAR_NAME
(за винятком додатка vue.js
, як пояснено нижче).
Переконайтесь, що .env
не знаходиться під контролем версій
# .gitgnore
.env*
!.env.example
Ваш файл README повинен містити такі інструкції:
My app
======...
Installation
-
Copy .env.example to .env and adjust the values where necessary.
Ось приклад файлу `.env.example`:
# .env.example HOST=localhost PORT=8080 VUE_APP_API_ROOT=https://localhost:8081 VUE_APP_API_KEY=SECRET
та відповідний `.env` файл:
# .env HOST=localhost PORT=20000 VUE_APP_API_ROOT=https://localhost:20001 VUE_APP_API_KEY=1234567890abcdef
Ваш файл `.env` повинен містити значення для вашого локального середовища. Таким чином ви можете використовувати власні налаштування, не втручаючись у налаштування інших розробників. Оскільки він знаходиться під контролем версій, файл `.env.example` не повинен містити чутливих або секретних значень.
Наведені вище приклади пропонують порт 8080 для локального запуску вашої програми, який було змінено на 20000. Це буде використано так:
# vue.config.js module.exports = { …, devServer: { host: process.env.HOST || localhost, open: true, port: process.env.PORT || 8080 }, … }
Зауважте, що `env.example` показує значення за замовчуванням, визначені в блоці коду вище.
=== Використання env vars через process.env
Усі змінні доступні на через `process.env.VAR_NAME`. З vue-cli, якщо ви хочете, щоб змінна була доступна у пакеті клієнта, ви повинні почингати її ім'я `VUE_APP_` (https://cli.vuejs.org/guide/mode-and-env.html#using-env -перемінний код-на стороні клієнта-код).
Код поза пакетом клієнтів (наприклад, vue.config.js) має доступ до всіх змінних середовища. У прикладі з попереднього пункту використовувались HOST та PORT.
=== Кращі практики
На відміну від офіційних документів `vue-cli`, я настійно рекомендую дотримуватися кращих практик `dotenv` та не використовувати специфічні для режиму файли env (наприклад, `.env.test`, `.env.develop` тощо). Env vars слід вводити лише під час збирання або запуску.
Крім того, я не рекомендую використовувати виклики до `process.env` у коді з кількох причин:
1. `process.env` - це інтерфейс між вашим додатком та навколишнім середовищем. Немає жодної причини допускати це всередину вашого коду.
2. Змінні, оброблені `dotenv`, завжди є рядками. Рано чи пізно це неминуче призводить до плутанини. Якщо я визначу флаг як env var (наприклад, для вмикання можливостей) в коді, я очікую, що він буде булевим. Отримання рядка призведе до плутанини, а потім маємо додати трохи дурного коду, щоб перевірити правдивість рядка. Загалом суцільна каша.
3. Програми Vue.js можуть мати багато знінних, і файл .`env` може швидко забитись. Якщо, як і я (і як і слідує бути), ви хочете впорядкувати своє оточення в алфавітному порядку, то стає важко чітко вказати, що потрібно визначати локально, що можна перевизначити, а що не можна перекривати. В ідеалі `.env` слід використовувати лише для змінних, які можна або потрібно перекрити локально.
=== Config.js
Як рішення, я хочу ввести, так сказати, «єдину точку входу», тобто єдиний фрагмент коду, який обробить усі змінні середовища для програми та поверне належним чином набране значення.
Ми можемо почати з цього:
[source,js]
# config.js const config = { apiBaseUrl: process.env.VUE_APP_API_BASE_URL, locale: process.env.VUE_APP_LOCALE, sso: { enabled: process.env.VUE_APP_SSO_ENABLED, … }, … }
export { config }
Для зручності це можна визначити як плагін Vue:
[source,js]
export default { install (Vue) { Vue.appConfig = config Vue.prototype.$appConfig = config } }
У своєму коді, замість доступу до env vars, ви отримуєте доступ до налаштувань конфігурації через `this.$appConfig` або `$appConfig`, наприклад, `this.$appConfig.apiBaseUrl` або `$appConfig.sso.enabled`.
Цей файл конфігурації також повинен містити відповідні типові параметри. Моя практика - визначати параметри-замовчування для локального середовища. Для розгортань на стороні сервера (розробка, стейдж, виробництво) я вважаю за краще чітко визначити всі змінні середовища під час збирання чи часу виконання, тому будь-що за замовчуванням буде перекрито.
Простий спосіб зробити це так:
[source,js]
# config.jsconst config = { apiBaseUrl: process.env.VUE_APP_API_BASE_URL || http://localhost:8081, locale: process.env.VUE_APP_LOCALE || en, sso: { enabled: process.env.VUE_APP_SSO_ENABLED || false }, … }
Однак я також хочу, щоб цей файл конфігурації надійно передав усі налаштування конфігурації відповідному типу. Для цього я використовую цю додаткову логіку:
[source,js]
# config.jsconst config = { apiBaseUrl: parse(process.env.VUE_APP_API_BASE_URL, http://localhost:8081), locale: parse(process.env.VUE_APP_LOCALE, en), sso: { enabled: parse(process.env.VUE_APP_SSO_ENABLED, false), … }, … }
function parse (value, fallback) { if (typeof value === undefined) { return fallback } switch (typeof fallback) { case boolean : return !!JSON.parse(value) case number : return JSON.parse(value) default : return value } }
Оскільки всі параметри конфігурації визначені в одному файлі, розробник може легко знайти, які налаштування доступні, і файл `.env.example` може бути зарезервований, щоб вказати лише ті змінні, які потрібно перекрити локально. Звичайно, самому .env-файлу потрібно було б визначити лише ті самі налаштування. У більшості випадків файли `.env.example` та `.env` можуть бути скорочені до нуля.
На даний момент ми досягли всіх заявлених цілей: єдиний файл, що забезпечує всі параметри конфігурації додатків на основі змінних середовища, завантажених через `dotenv`, перетворені у відповідний тип та з можливістю визначати параметри за замовчуванням, щоб файл `.env` міг бути скорочений до мінімуму.
Але ми можемо піти на крок далі і набрати ще більше значення, додавши підтримку перемикань функцій.
=== Перемикачі функцій
Перемикачі функцій надзвичайно корисні, і ви дуже хочете їх використовувати. Для цього доступно кілька гарних пакетів, але це так просто реалізувати в `config.js`, що краще уникнути ще однієї залежності.
[source,js]
# config.js
const config: { …,
features: {
example: parse(process.env.VUE_APP_FEATURE_EXAMPLE, false),
...
}, ...
}
function feature (name) { return config.features[name] }
export default { install (Vue) { Vue.appConfig = config Vue.feature = feature Vue.prototype.$appConfig = config Vue.prototype.$feature = feature } }
Для визначення перемикання функції додайте дочірню властивість у `config.features`. За домовленістю, щоб все було просто, я називаю відповідну env var після перемикання з префіксом `VUE_APP_FEATURE_`. Наприклад, перемикання функції `example` визначається змінною `VUE_APP_FEATURE_EXAMPLE`.
Щоб перевірити, чи увімкнено цю функцію, викличте цей `this.$feature('example')` або `$feature('example')`.
=== Висновок
Here is the full config.js file:
[source,js]
# config.jsconst config = { …, features: { … }. … }
function feature (name) { return config.features[name] }
function parse (value, fallback) { if (typeof value === undefined) { return fallback } switch (typeof fallback) { case boolean : return !!JSON.parse(value) case number : return JSON.parse(value) default : return value } }
export { config }
export default { install (Vue) { Vue.appConfig = config Vue.feature = feature Vue.prototype.$appConfig = config Vue.prototype.$feature = feature } }
Скопіюйте цей файл у каталог `src/` та додайте його до `main.js`:
[source,js]
# main.jsimport Vue from 'vue` import configPlugin from '@/config’Vue.use(configPlugin)