Skip to content

Commit

Permalink
docs: update ru translation for env vars page (#1184)
Browse files Browse the repository at this point in the history
  • Loading branch information
ronanru authored Feb 8, 2023
1 parent e365b49 commit 8f65c39
Showing 1 changed file with 77 additions and 38 deletions.
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`._

┣ 📄 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 поможет вам убедиться, что вы ввели ключи из обеих схем.

```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`, валидация пройдет успешно. Следовательно, у нас есть единая входная точка для всех переменных среды.

```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` и использовать их как вы обычно использовали бы. Если вы попробуете импортировать этот файл на стороне клиента и получить серверную переменную, вы получите ошибку:

```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

1 comment on commit 8f65c39

@vercel
Copy link

@vercel vercel bot commented on 8f65c39 Feb 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.