Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Переменные окружения

Переменные окружения — настройки, которые задаются снаружи приложения: секрет сессий, путь к базе, ключи внешних сервисов. На вашем компьютере и на сервере они разные, а в коде остаются одни и те же имена. Так секреты не попадают в репозиторий.

Файл .env

Создайте в корне проекта файл .env:

SESSION_SECRET=long-random-string-for-dev
DATABASE_PATH=blog.db
VITE_SITE_NAME=Мой блог

Сервер разработки npm run dev читает этот файл при запуске. Добавьте .env в .gitignore, а в репозиторий положите .env.example с теми же именами и пустыми значениями — чтобы другие разработчики знали, что заполнить.

На сервере: process.env

В загрузчиках, действиях и файлах .server.ts переменные доступны через process.env:

// app/db.server.ts
import Database from "better-sqlite3";
 
export const db = new Database(process.env.DATABASE_PATH ?? "blog.db");

Значение — строка или undefined, если переменная не задана. Поэтому рядом указывают значение по умолчанию или проверяют наличие.

Обязательная переменная

Для секретов значения по умолчанию быть не должно. Проверьте переменную сразу при загрузке модуля:

// app/sessions.server.ts
const secret = process.env.SESSION_SECRET;
if (!secret) {
  throw new Error("Не задана переменная SESSION_SECRET");
}

Если забыть переменную на сервере, приложение остановится с понятной ошибкой при старте, а не будет работать с ненадёжным секретом.

В браузере

Код компонентов выполняется и в браузере, где process.env нет. Vite подставляет в браузерный код только переменные с приставкой VITE_, через import.meta.env:

// app/routes/layout.tsx
<header>{import.meta.env.VITE_SITE_NAME}</header>

Значение вшивается в JavaScript при сборке, поэтому его увидит любой посетитель. Приставку VITE_ дают только тому, что не секретно.

Через загрузчик

Если значение нужно в браузере, но должно браться при запуске, а не при сборке, передайте его из загрузчика:

// app/root.tsx
export async function loader() {
  return { contactEmail: process.env.CONTACT_EMAIL ?? "hello@example.com" };
}

Компонент получит его в loaderData, как любые другие данные.

Где нужноКак читать
loader, action, .server.tsprocess.env.ИМЯ
Компонент, не секрет, известно при сборкеimport.meta.env.VITE_ИМЯ
Компонент, значение с сервераВернуть из loader

Частая ошибка

Обратиться к process.env.SESSION_SECRET прямо в теле компонента. На сервере это сработает, а в браузере при гидратации будет ошибка process is not defined или пустое значение. Секреты читают только в серверном коде, а в компонент передают уже готовый результат.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.