sadrix logoSadriX
Минцифры готовит обязательную регистрацию IMEI смартфонов, купленных за границей
Гайды

Как правильно настроить переменные окружения Next.js на продакшене

Полный гайд: настройка, разграничение доступа, деплой и защита секретов

09 317 просмотров6 мин
0
Поделиться:TelegramVK

Введение

Переменные окружения — это основа конфигурации любого современного веб-приложения. В Next.js они позволяют хранить API-ключи, строки подключения к базе данных, URL внешних сервисов и другие параметры, которые не должны попадать в репозиторий. Однако при переносе проекта на продакшен многие разработчики сталкиваются с тем, что переменные «не подхватываются», оказываются доступны на клиенте или вовсе ломают сборку.

В этом руководстве мы разберём, как правильно настроить env-переменные Next.js для продакшена: какие бывают типы переменных, как их использовать в коде, как деплоить на разные платформы и каких ошибок избегать. Материал актуален для Next.js 13+ (App Router) и 12+ (Pages Router) — различия будут отмечены отдельно.

Требования

  • Node.js 18.17 или новее (для Next.js 14+).

  • Проект на Next.js (версия 12 и выше).

  • Базовое понимание процесса сборки (next build) и запуска (next start).

  • Доступ к панели управления хостингом (Vercel, Docker, VPS и т.п.).

  • Текстовый редактор или IDE.

Шаг 1. Разберитесь с типами переменных в Next.js

Next.js делит переменные окружения на две большие категории:

1. Серверные — доступны только в серверном коде: API-роуты, серверные компоненты, getServerSideProps, getStaticProps, middleware. Они не попадают в клиентский бандл. 2. Клиентские — доступны в браузере. Чтобы переменная стала клиентской, её имя должно начинаться с префикса NEXT_PUBLIC_.

Важно: любые переменные без префикса NEXT_PUBLIC_ не будут доступны в клиентском коде, даже если вы попытаетесь к ним обратиться. Это сделано для безопасности.

Также существует понятие «встроенных» переменных, которые Next.js подставляет автоматически: NODE_ENV, NEXT_PUBLIC_VERCEL_URL (на Vercel) и другие.

Шаг 2. Создайте файлы .env для разных окружений

Next.js поддерживает несколько файлов окружения, которые загружаются в определённом порядке:

  • .env — общие настройки для всех окружений.

  • .env.local — локальные переопределения, игнорируются Git.

  • .env.development — для режима разработки.

  • .env.production — для продакшен-сборки.

  • .env.test — для тестов.

Приоритет загрузки: .env.$(NODE_ENV).local > .env.local > .env.$(NODE_ENV) > .env.

Создайте в корне проекта файл .env.local для секретов разработки и .env.production для продакшен-значений (без секретов, если файл попадает в репозиторий). Не забывайте добавлять .env*.local в .gitignore.

Пример .env.local:

DATABASE_URL=postgres://user:pass@localhost:5432/mydb
NEXT_PUBLIC_API_URL=http://localhost:3000/api
SECRET_KEY=dev-secret

Шаг 3. Используйте переменные в серверном коде

В серверных компонентах, API-роутах и функциях вроде getServerSideProps переменные доступны через process.env:

// app/api/data/route.js
export async function GET() {
  const dbUrl = process.env.DATABASE_URL;
  // ...
}

В Pages Router:

export async function getServerSideProps() {
  const key = process.env.SECRET_KEY;
  // ...
}

Серверные переменные не инлайнятся в клиентский бандл, поэтому их безопасно использовать для секретов.

Шаг 4. Настройте клиентские переменные с префиксом NEXT_PUBLIC_

Если значение нужно в браузере (например, публичный URL API), добавьте префикс NEXT_PUBLIC_:

NEXT_PUBLIC_API_URL=https://api.example.com

Использование в компоненте:

const apiUrl = process.env.NEXT_PUBLIC_API_URL;

Next.js заменит process.env.NEXT_PUBLIC_API_URL на конкретное значение во время сборки. Это значит, что после изменения переменной требуется пересобрать приложение.

Важно: не добавляйте префикс NEXT_PUBLIC_ к секретам — они станут видны любому пользователю в исходниках страницы.

Шаг 5. Учтите особенности App Router (Next.js 13+)

В App Router серверные компоненты по умолчанию выполняются на сервере, поэтому process.env работает как обычно. Однако если вы используете клиентские компоненты ('use client'), доступны только переменные с NEXT_PUBLIC_.

Для динамических значений на сервере можно применять unstable_noStore или динамический рендеринг, чтобы переменные читались в рантайме, а не на этапе сборки. Но помните: в серверных компонентах process.env читается при каждом запросе, если страница динамическая.

Шаг 6. Настройте переменные для продакшен-сборки

При запуске next build Next.js загружает .env.production (и .env.local, если он есть). Если вы собираете проект в CI/CD, убедитесь, что все нужные переменные доступны в окружении сборки.

Для серверных переменных, которые должны читаться в рантайме (например, при запуске next start), они должны быть заданы в окружении процесса. Next.js не подгружает .env.production автоматически при next start — только при сборке. Поэтому на продакшене переменные обычно передают через панель хостинга или системные env.

Шаг 7. Деплой на Vercel

Vercel — самый простой способ. В настройках проекта (Settings → Environment Variables) добавьте переменные для окружений Production, Preview и Development. После добавления нужно перезапустить деплой, чтобы изменения вступили в силу.

Особенности:

  • Переменные с NEXT_PUBLIC_ доступны на клиенте.

  • Секреты без префикса доступны только серверным функциям.

  • Можно задавать разные значения для Preview и Production.

Шаг 8. Деплой в Docker

При сборке Docker-образа передавайте переменные через ARG и ENV:

ARG NEXT_PUBLIC_API_URL
ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL
RUN npm run build

Серверные секреты лучше передавать в рантайме через docker run -e или docker-compose, чтобы они не попали в слои образа. Помните: переменные, использованные на этапе сборки, «запекаются» в бандл.

Шаг 9. Деплой на собственный сервер (VPS)

Если вы используете next start на VPS, задайте переменные в systemd-юните, в файле .env.production рядом с проектом (но тогда Next.js не загрузит его автоматически при старте) или через менеджер процессов (PM2).

Надёжный вариант — экспортировать переменные в shell перед запуском:

export DATABASE_URL=...
export NEXT_PUBLIC_API_URL=...
npm run start

Либо используйте пакет dotenv и загружайте .env.production вручную в кастомном сервере.

Шаг 10. Проверьте, что переменные не утекли в клиент

После сборки можно проанализировать клиентский бандл на наличие секретов. Ищите строки, которые не должны быть публичными. Если секрет попал в .next/static, значит, вы случайно использовали его в клиентском компоненте или дали префикс NEXT_PUBLIC_.

Также полезно добавить в CI шаг с grep по собранным файлам на предмет запрещённых значений.

Шаг 11. Валидируйте переменные при старте

Чтобы приложение не падало в рантайме из-за отсутствующей переменной, добавьте проверку. Например, создайте файл env.js:

const required = ['DATABASE_URL', 'SECRET_KEY'];
for (const key of required) {
  if (!process.env[key]) {
    throw new Error(`Missing env: ${key}`);
  }
}

Импортируйте его в next.config.js или в серверной точке входа. Это поможет выявить проблему сразу после деплоя.

Шаг 12. Используйте типизацию для TypeScript

Чтобы избежать опечаток, объявите типы для process.env в env.d.ts:

declare namespace NodeJS {
  interface ProcessEnv {
    DATABASE_URL: string;
    NEXT_PUBLIC_API_URL: string;
  }
}

Это даст автодополнение и проверку на этапе компиляции.

Типичные ошибки

1. Использование секретов с префиксом NEXT_PUBLIC_ — приводит к утечке ключей в клиентский бандл. 2. Ожидание, что .env.production загрузится при next start — Next.js загружает env-файлы только на этапе сборки; в рантайме переменные нужно передавать через окружение. 3. Изменение переменной без пересборки — клиентские переменные инлайнятся при сборке, поэтому после изменения требуется новый билд. 4. Отсутствие переменных в CI/CD — сборка падает или получает неверные значения. 5. Хранение .env.local в Git — секреты попадают в репозиторий. 6. Использование process.env в клиентском компоненте без префикса — переменная будет undefined. 7. Забыли добавить переменные в Vercel/хостинг — приложение работает локально, но не на проде. 8. Динамическое чтение серверных переменных в статически сгенерированных страницах — значения фиксируются на этапе сборки.

FAQ

В: Можно ли использовать переменные окружения в next.config.js? О: Да, но они доступны только на этапе сборки. Для клиента их нужно явно прокинуть через env в конфиге (не рекомендуется для секретов).

В: Как передать переменные в middleware? О: Middleware выполняется на сервере (Edge), поэтому process.env доступен. Учтите, что на Edge некоторые Node.js API недоступны.

В: Что делать, если переменная нужна и на клиенте, и на сервере? О: Создайте две переменные: одну с NEXT_PUBLIC_ для клиента, другую без префикса для сервера, если значения различаются. Либо используйте одну NEXT_PUBLIC_, если значение не секретное.

В: Как обновить переменные на Vercel без пересборки? О: Никак для клиентских переменных — нужен редеплой. Серверные переменные в Serverless Functions подхватываются при следующем вызове функции, но для надёжности лучше перезапустить деплой.

В: Поддерживает ли Next.js переменные из системного окружения? О: Да, process.env включает как переменные из .env-файлов, так и системные.

Итог

Правильная настройка переменных окружения в Next.js на продакшене строится на трёх принципах: чёткое разделение серверных и клиентских переменных, передача секретов только через защищённые каналы и обязательная пересборка при изменении клиентских значений. Используйте префикс NEXT_PUBLIC_ только для действительно публичных данных, валидируйте переменные при старте и не храните секреты в репозитории. Следуя шагам из этого руководства, вы сможете безопасно конфигурировать приложение на Vercel, в Docker или на собственном сервере.

Читайте также

Комментарии

Комментарии доступны только зарегистрированным пользователям. Войти

  • Пока нет комментариев. Будьте первым.