Добавить объявление

Знаете Flutter? Значит, можете писать бэкенд на Dart

Если вы работаете с Flutter, вы знаете Dart. Вы понимаете async/await, работаете с моделями и репозиториями, привыкли к чистой архитектуре. Вы запускали приложения на реальных устройствах. Между этим и умением написать и запустить рабочий бэкенд - пропасть меньше, чем кажется. Не нужно учить новый язык. Нужно понять, как Dart работает, когда нет виджетов, нет BuildContext, нет Flutter. Есть только процесс, который принимает HTTP-запросы, ходит в базу данных и отправляет ответы.

Автор статьи показывает этот путь на примере API для управления пользователями и профилями. Все на знакомом Dart и фреймворке Shelf. Проект поднимается в Docker с PostgreSQL, проверяет пользователей через JWT-токены и деплоится на Fly.io.

Как Dart работает на сервере:


В Flutter-приложении ваш код работает поверх огромного количества логики: дерево виджетов, пайплайн рендеринга, управление состоянием, обработка событий платформы. На сервере ничего этого нет.

Есть процесс, который слушает порт, получает HTTP-запросы, делает работу и отправляет ответы. В стандартной библиотеке Dart есть все необходимое для этого на самом низком уровне.

import 'dart:io';

void main() async {
final server = await HttpServer.bind('0.0.0.0', 8080);
print('Сервер запущен на порту 8080');

await for (final request in server) {
request.response
..statusCode = 200
..write('Привет из Dart')
..close();
}
}

Это рабочий HTTP-сервер. Никаких пакетов, никаких фреймворков. Каждый запрос приходит через HttpServer, и вы пишете ответ напрямую.

Но как только появляются маршруты, middleware, аутентификация и обработка ошибок, работать с dart:io становится неудобно. Здесь в игру вступает Shelf.

Что такое Shelf:


Shelf - это библиотека для создания веб-серверов. Она не пытается быть полноценным фреймворком. Вместо этого она дает базовые кирпичики, из которых вы собираете именно то, что нужно.

В Shelf есть четыре ключевых понятия:

  • Handler - функция, которая принимает Request и возвращает Response. Все в Shelf в итоге сводится к хендлеру.

  • Middleware - функция, которая оборачивает хендлер, добавляя поведение до или после его выполнения. Логирование, аутентификация и обработка ошибок - это middleware.

  • Pipeline - цепочка middleware с хендлером в конце. Запрос проходит через все middleware, прежде чем добраться до хендлера.

  • Router - сопоставляет URL-паттерны и HTTP-методы с конкретными хендлерами.


Если вы использовали навигацию в Flutter или что-то похожее на провайдеры, модель композиции будет понятна. Маленькие, независимые части собираются в работающее целое.

Структура проекта:


Автор статьи предлагает структуру, которая будет знакома любому Flutter-разработчику:

user_profile_api/
bin/
server.dart - точка входа
lib/
config/ - настройки и подключение к БД
handlers/ - хендлеры для эндпоинтов
middleware/ - логирование, ошибки, аутентификация
models/ - модели данных
repositories/ - работа с базой данных
services/ - бизнес-логика (JWT, хеширование)
router.dart - маршрутизация
migrations/ - SQL-скрипты
docker-compose.yml
Dockerfile
.env

Модели, репозитории, сервисы - это те же понятия, что и в Flutter-проекте. Хендлеры заменяют ViewModel или контроллеры. Middleware - перехватчики.

База данных и миграции:


В проекте используется PostgreSQL. Все поднимается через Docker Compose. Миграции применяются автоматически при старте приложения.

Структура базы данных простая: таблица users и таблица profiles, связанная один к одному. Код написан так, что разработчику не нужно писать сырые SQL-запросы в хендлерах - вся работа с базой инкапсулирована в репозиториях.

Аутентификация и защита:


Автор использует JWT-токены. Пароли хешируются с помощью bcrypt. Регистрация и логин - публичные эндпоинты. Все остальное защищено middleware, который проверяет наличие и валидность токена перед тем, как пустить запрос дальше.

Особенно хорошо сделан один момент: при неудачной попытке входа сервер возвращает общее сообщение «Неверный email или пароль», а не уточняет, что именно не так. Это защита от перебора пользователей.

Обработка ошибок:


Вместо того чтобы в каждом хендлере писать try/catch, автор выносит обработку ошибок в отдельное middleware. Это гарантирует единый формат ответа для всех ошибок и, что важно, скрывает от клиента внутренние детали. Пользователь никогда не увидит стектрейс или детали ошибки базы данных.

Деплой:


Автор статьи показывает два пути. Локально - через Docker Compose, где приложение и база данных поднимаются вместе. Продакшен - на Fly.io, где управляемый PostgreSQL и автоматический TLS настроены практически из коробки.

Вывод:


Эта статья - хороший пример того, что знание Dart не заканчивается на Flutter. Те же модели, репозитории, асинхронность и архитектурные подходы работают и на сервере. Нужно только сменить контекст: вместо виджетов - обработка запросов, вместо State - база данных.

Shelf не делает за вас выборов. Он дает кирпичики, а архитектуру вы собираете сами. Это философски близко к Flutter, где вы тоже строите UI из базовых компонентов.

Если вы знаете Dart, бэкенд уже не выглядит чем-то недоступным.
30.06.2026 50 589