Пошаговый практический гайд по интеграции Drizzle ORM с Next.js для получения полностью типобезопасного backend на TypeScript. Ожидаемое время выполнения — 60–120 минут в зависимости от опыта и окружения.
0
Статья была полезной?
Комментарии (0)
Войдите или зарегистрируйтесь, чтобы оставить комментарий
Загрузка комментариев…
Почему Drizzle?
Drizzle ORM ориентирован на типобезопасность и генерацию типов на базе схемы базы данных, что упрощает работу с TypeScript в backend-части приложений. В 2025–2026 годах Drizzle активно развивается и предлагает низкоуровневые инструменты для работы с SQL без лишней абстракции.
Что вы изучите
Установка Next.js 14 (релиз 2025) и Drizzle ORM 2.x (релизы 2025–2026) в проект на TypeScript.
Определение схем таблиц с Drizzle и TypeScript-типизация результатов.
Генерация и применение миграций через drizzle-kit.
Использование запросов Drizzle внутри Server Actions Next.js (app router) безопасным способом.
Развёртывание через Docker с образами node:20-alpine и postgres:16-alpine.
Требования
Node.js 20.x (LTS, проверено в 2026). Рекомендуемая память: минимум 4 GB для разработки, 1–2 GB можно для контейнеров на CI.
PostgreSQL 16 (релиз 2023), образ postgres:16-alpine (~100 MB).
Docker Engine (для развёртывания) и Docker Compose 1.29+/v2 (~демон запускается за 1–3 с на SSD).
Необязательно: pnpm 8.x, но можно использовать npm 10+ или yarn 4+.
Шаг 1: установка
Команда создаёт проект Next.js 14 и устанавливает Drizzle ORM с драйвером PostgreSQL. В примере используется npm. Ожидаемое время выполнения: 1–3 минуты на fast SSD и интернет 100 Mbps.
# 1) Создать проект Next.js (CLI Next 14)
npm init next@14 my-app --typescript
cd my-app
# 2) Установить Drizzle, drizzle-kit, драйвер pg и типы
npm install drizzle-orm drizzle-kit pg @types/pg
# 3) Установить дополнительные утилиты для разработки
npm install -D ts-node dotenv
Объяснение: первая команда создаёт шаблон Next.js с app router и TypeScript. Вторая устанавливает основные пакеты: drizzle-orm (runtime + типы), drizzle-kit (миграции), pg (Postgres driver).
Ожидаемый вывод (усечённо):
+ drizzle-orm@2.x
+ drizzle-kit@2.x
+ pg@8.x
added 120 packages, and audited 121 packages in 2s
Типичная ошибка и фикс:
Ошибка:Error: pg-native bindings not found. Это бывает если установлены бинарные зависимости или старая сборка.
Фикс: Убедитесь, что вы используете чистую версию pg без опций native. Если ошибка при установке нормальных зависимостей — установите build-tools: на Ubuntu sudo apt-get install build-essential libpq-dev, затем повторите npm install.
Шаг 2: схема таблиц
Определим схему пользователей и постов с Drizzle в файле src/db/schema.ts. Время написания: 5–10 минут. Код генерирует TypeScript-типы автоматически.
Объяснение: мы используем pgTable из drizzle-orm/pg-core, задаём колонки и ограничения. На основе этих объявлений Drizzle генерирует типы для запросов и результатов.
Ожидаемый вывод при компиляции TypeScript (npm run build или tsc --noEmit):
Found 0 errors in 42 files.
Типичная ошибка и фикс:
Ошибка:Cannot find module 'drizzle-orm/pg-core'.
Фикс: Проверьте, что пакет drizzle-orm установлен и версия совпадает с документацией. Перезапустите IDE/TypeScript server, удалите node_modules и выполните npm ci.
Скриншот файла schema.ts с таблицами users и posts
Шаг 3: миграции
Используем drizzle-kit для генерации и применения миграций. Пример опирается на drizzle-kit версии 2.x (релизы 2025–2026). Время: 1–2 минуты для генерации и 1–3 секунды для применения в локальном контейнере.
Ошибка:failed to connect to server: Connection refused (0x0000274D/10061). Это означает, что DATABASE_URL не указывает на работающий Postgres на порту 5432.
Фикс: Запустите Postgres контейнер (см. шаг 5) или локально: docker run --rm -e POSTGRES_PASSWORD=pass -p 5432:5432 -d postgres:16-alpine. Проверьте строку подключения: export DATABASE_URL="postgres://postgres:pass@localhost:5432/postgres".
Шаг 4: queries в server actions
Next.js app router поддерживает Server Actions через директиву "use server". Здесь показан пример безопасного доступа к Drizzle внутри server action. Время реализации: 5–15 минут.
// src/db/client.ts
import { drizzle } from 'drizzle-orm/node-postgres'
import postgres from 'postgres'
import { env } from 'process'
const sql = postgres(env.DATABASE_URL!)
export const db = drizzle(sql)
// src/app/actions/postActions.ts
'use server'
import { db } from '@/db/client'
import { posts } from '@/db/schema'
export async function createPost(data: { title: string; body: string; authorId: number }) {
const res = await db.insert(posts).values({
title: data.title,
body: data.body,
author_id: data.authorId,
}).returning()
return res[0]
}
Пример использования в серверном компоненте или action handler:
import { createPost } from './actions/postActions'
export default async function Page() {
const newPost = await createPost({ title: 'Hello', body: 'World', authorId: 1 })
// newPost типизирован как RowType для posts
return {JSON.stringify(newPost)}
}
Ожидаемый вывод при вызове createPost (в консоли или в браузере, если отобразить):
Ошибка:TypeError: db.insert is not a function. Это случается, если импортирован неправильный db клиент (например, клиент для браузера).
Фикс: Убедитесь, что файл src/db/client.ts экспортирует серверный экземпляр (используйте drizzle-orm/node-postgres или postgres), и не импортируйте его в клиентские компоненты. Для предотвращения ошибок сериализации экспортируйте только функции, которые выполняют запросы на сервере.
Скриншот server action в Next.js с вызовом createPost через Drizzle
Шаг 5: тестирование и развёртывание (Docker)
Минимальный рабочий Docker-стек: приложение на Node 20 и Postgres 16. Размер итогового образа приложения с multi-stage сборкой будет ~80–120 MB при использовании node:20-alpine. Время сборки на CI: 30–120 секунд в зависимости от сети и кэша.
# Dockerfile (multi-stage)
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json pnpm-lock.yaml* ./
RUN npm ci --prefer-offline
COPY . .
RUN npm run build
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/.next .next
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json
EXPOSE 3000
CMD ["node", ".next/server/app.js"]
Ожидаемый вывод при docker-compose up --build (усечённо):
Building app
Step 1/10 : FROM node:20-alpine AS builder
---> 2a3b... (image id)
Successfully built 5f3c...
Creating project_db_1 ... done
Creating project_app_1 ... done
Типичная ошибка и фикc:
Ошибка:ECONNREFUSED при попытке подключиться к БД сразу после старта контейнеров.
Фикс: Postgres может инициализироваться несколько секунд. Используйте скрипт ожидания (wait-for) или опцию healthcheck и повторные попытки подключения в коде. В docker-compose можно указать healthcheck и использовать depends_on.condition: service_healthy для безопасного старта.
Что лучше Prisma?
Prisma — зрелая ORM с мощным генератором миграций и широким экосистемным покрытием; она предоставляет удобный DSL и генерацию клиентского API. Drizzle фокусируется на минимальной runtime-слое и прямой работе с SQL, выдавая строгие TypeScript-типы на уровне схемы и запросов.
Короткое сравнение по критериям:
Типобезопасность: обе библиотеки дают статическую типизацию; Drizzle ближе к SQL и даёт явные типы по колонкам, Prisma предлагает удобный типизированный клиент на основе schema.prisma.
Контроль SQL: Drizzle менее абстрагирует SQL и оставляет больше контроля, Prisma генерирует SQL за вас через клиент.
Миграции: Prisma имеет зрелую систему миграций; Drizzle использует drizzle-kit, которая в 2025–2026 годах догоняет по функционалу и отлично подходит для проектов, где важна прозрачность SQL.
Продуктивность и поверхность API: Prisma предлагает более дружелюбный DSL для быстрого старта; Drizzle предпочтительнее, если нужен контроль и минимальный runtime.
Частые вопросы
Как подключить Drizzle к существующей базе данных?
Создайте схему в виде таблиц Drizzle, но если у вас уже есть структура в базе, используйте drizzle-kit в режиме сравнения схемы или создайте миграцию вручную, экспортируя текущую структуру как первый миграционный скрипт. Для минимального риска снимите дамп структуры с помощью pg_dump -s, сохраните в каталог миграций и примените на тестовом окружении. Перед применением миграций на проде всегда проверяйте SQL и выполняйте backup.
Что делать при ошибке permission denied for relation?
Эта ошибка указывает, что пользователь БД не имеет прав на таблицу. Проверьте пользователя, указанный в DATABASE_URL, и назначьте права: подключитесь от суперпользователя и выполните GRANT ALL PRIVILEGES ON TABLE public.users TO your_user; или назначьте роль с соответствующими правами. Также проверьте схему (namespace) таблиц — возможно, таблицы созданы в другой схеме.
Почему запросы Drizzle медленнее на CI, чем локально?
Частые причины: сеть (CI может иметь ограниченную пропускную способность), отсутствие кэша зависимостей и медленный диск. Для ускорения на CI используйте кэширование слоя node_modules, используйте контейнеры с SSD, настройте пул соединений и уменьшите время создания БД(instance) на CI, например, используйте подготовленные снимки базы или тестовые контейнеры с предзаполненной схемой.
Где лучше хранить инстанс db в Next.js?
Храните экземпляр DB в файловой области сервера (например, src/db/client.ts) и импортируйте только в server actions или server components. Не передавайте объект DB в клиентские компоненты и не сериализуйте его. В случае серверлесс-среды используйте ленивую инициализацию и пул соединений вместе с библиотеками, адаптированными под serverless (но при использовании postgres/drizzle предпочтительнее держать одно соединение-пул при долгоживущих процессах).
Смотрите также: Проекты и Топ статей на ресурсе для примеров развёртывания и CI/CD.
Комментарии (0)
Войдите или зарегистрируйтесь, чтобы оставить комментарий
Загрузка комментариев…