Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: update ru translation for env vars page #1184

Merged
merged 6 commits into from
Feb 8, 2023
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 77 additions & 38 deletions www/src/pages/ru/usage/env-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,89 +5,128 @@ layout: ../../../layouts/docs.astro
lang: ru
---

Create-T3-App использует [Zod](https://github.com/colinhacks/zod) для проверки переменных среды во время выполнения _и_ во время сборки, предоставляя дополнительные файлы в директории `env`:
Create-T3-App использует [Zod](https://github.com/colinhacks/zod) для проверки переменных среды во время выполнения _и_ во время сборки, предоставляя дополнительную логику в файле `src/env.mjs`:

📁 src/env
## env.mjs

┣ 📄 client.mjs
_TLDR; Если вам нужно добавить новую переменную среды, вы должны ее добавить как в `.env` так и обозначить для нее валидатор в `src/env.mjs`._
ronanru marked this conversation as resolved.
Show resolved Hide resolved

┣ 📄 schema.mjs
Это файл разделен на две части: схема и объект для деструктуризации и логика для валидации. Логику валидации трогать не стоит.

┣ 📄 server.mjs

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

_Короче; Если вы хотите добавить новую переменную среды, вы должны добавить ее как в `.env`, так и определить валидатор в `env/schema.mjs`._

## schema.mjs

Это файл с которым вы будете работать. Он содержит две схемы, одну для переменных среды на стороне сервера, а другую для клиента, а также объект `clientEnv`.

```ts:env/schema.mjs
export const serverSchema = z.object({
// DATABASE_URL: z.string().url(),
```ts:env.mjs
const server = z.object({
NODE_ENV: z.enum(["development", "test", "production"]),
});

export const serverEnv = {
// DATABASE_URL: process.env.DATABASE_URL,
};

export const clientSchema = z.object({
// NEXT_PUBLIC_WS_KEY: z.string(),
const client = z.object({
// NEXT_PUBLIC_CLIENTVAR: z.string(),
});

export const clientEnv = {
// NEXT_PUBLIC_WS_KEY: process.env.NEXT_PUBLIC_WS_KEY,
const processEnv = {
NODE_ENV: process.env.NODE_ENV,
// NEXT_PUBLIC_CLIENTVAR: process.env.NEXT_PUBLIC_CLIENTVAR,
};
```

### Схема сервера

Определите схему переменных среды на стороне сервера здесь.

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

### Схема клиента

Определите схему переменных среды на стороне клиента здесь.

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

### Объект clientEnv
### Объект processEnv

Деструктурируйте `process.env` здесь.

Нам нужен объект JavaScript, который мы можем деструктурировать нашими схемами Zod и из-за того, как Next.js обрабатывает переменные среды, вы не можете деструктурировать `process.env` как обычный объект, поэтому нам нужно сделать это вручную.

TypeScript поможет вам убедиться, что вы ввели ключи в `clientEnv` и `clientSchema`.
TypeScript поможет вам убедиться, что вы ввели ключи в из обоих схем.
ronanru marked this conversation as resolved.
Show resolved Hide resolved

```ts
// ❌ This doesn't work, we need to destruct it manually
// ❌ Это не работает, нужно деструктурировать вручную
const schema = z.object({
NEXT_PUBLIC_WS_KEY: z.string(),
});

const validated = schema.parse(process.env);
```

## server.mjs & client.mjs
### Логика валидации

_Для заинтересованного читателя:_

<details>
<summary>Advanced: Логика валидации</summary>

Здесь происходит валидация и экспортируются проверенные объекты. Вам не нужно изменять эти файлы.
В зависемости от среды (сервер или клиент) мы валидируем либо обе, либо только клиентскую схему. Это значить, что, несмотря на то, что серверные переменные будут иметь значение `undefined`, валидация пройдет успешно. Это значит что у нас есть единая входная точка для всех переменных среды.
ronanru marked this conversation as resolved.
Show resolved Hide resolved

```ts:env.mjs
const isServer = typeof window === "undefined";

const merged = server.merge(client);
const parsed = isServer
? merged.safeParse(processEnv) // <-- Если на сервере, валидировать все переменные
: client.safeParse(processEnv); // <-- Если на клиенте, только клиентские

if (parsed.success === false) {
console.error(
"❌ Invalid environment variables:\n",
...formatErrors(parsed.error.format()),
);
throw new Error("Invalid environment variables");
}
```

Затем мы используем объект Proxy чтобы выкидывать ошибки, если вы попытаетесь получить доступ к серверным переменным среды на клиенте.

```ts:env.mjs
// Прокси позволяет переопределить геттер
export const env = new Proxy(parsed.data, {
get(target, prop) {
if (typeof prop !== "string") return undefined;
// На клиенте разрешаются только переменные начинающиеся с NEXT_PUBLIC_
if (!isServer && !prop.startsWith("NEXT_PUBLIC_"))
throw new Error(
"❌ Attempted to access serverside environment variable on the client",
);
return target[prop]; // <-- В противном случае, возвращаем нужное значение
},
});
```

</details>

## Использование переменных среды

Когда вы хотите использовать переменные среды, вы можете импортировать их из `env/client.mjs` или `env/server.mjs` в зависимости от того, где вы хотите их использовать:
Когда вы хотите использовать переменные среды, вы можете импортировать их из `env.mjs` и использовать их как вы обычно использовали бы. Если вы попробуете импортировать этот файл на клиенте и получить серверную переменную, вы получите ошибку:
ronanru marked this conversation as resolved.
Show resolved Hide resolved

```ts:pages/api/hello.ts
import { env } from "../../env.mjs";

// `env` is fully typesafe and provides autocompletion
// `env` полностью типобезопасно и предоставляет автокомплит
const dbUrl = env.DATABASE_URL;
```

```ts:pages/index.tsx
import { env } from "../env.mjs";

// ❌ Это даст ошибку
const dbUrl = env.DATABASE_URL;

// ✅ Тут все ОК
const wsKey = env.NEXT_PUBLIC_WS_KEY;
```

## .env.example

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

Некоторые фреймворки и инструменты сборки, такие как Next.js, предлагают хранить секреты в файле `.env.local` и коммитить файлы `.env` в ваш проект. Это не рекомендуется, поскольку это может облегчить случайный коммит секретов в ваш проект. Вместо этого мы рекомендуем хранить секреты в `.env`, держать ваш файл `.env` в `.gitignore` и коммитить только файлы `.env.example` в ваш проект.

## Добавление переменных среды
Expand All @@ -96,13 +135,13 @@ const dbUrl = env.DATABASE_URL;

📄 `.env`: Введите переменную среды, как обычно делаете в файле `.env`, т.е. `KEY=VALUE`

📄 `schema.mjs`: Добавьте соответствующую логику проверки для переменной среды, определив схему Zod, например `KEY: z.string()`
📄 `env.mjs`: Добавьте соответствующую логику проверки для переменной среды, определив схему Zod, например `KEY: z.string()`, затем деструкткрируйте переменную из `proccess.env` в объект `processEnv`, например `KEY: process.env.KEY`.

Опционально, вы также можете обновлять файл `.env.example`:

📄 `.env.example`: Введите вашу переменную среды, но убедитесь, что не включаете значение, если оно является секретным, т.е. `KEY=VALUE` или `KEY=`

### Например
### Пример

_Я хочу добавить мой Twitter API токен в качестве переменной среды на стороне сервера_

Expand All @@ -112,15 +151,15 @@ _Я хочу добавить мой Twitter API токен в качестве
TWITTER_API_TOKEN=1234567890
```

2. Добавьте переменную среды в `schema.mjs`:
2. Добавьте переменную среды в `env.mjs`:

```ts
export const serverSchema = z.object({
export const server = z.object({
// ...
TWITTER_API_TOKEN: z.string(),
});

export const serverEnv = {
export const processEnv = {
// ...
TWITTER_API_TOKEN: process.env.TWITTER_API_TOKEN,
};
Expand Down