В чем разница между dependencies и dev_dependencies в pubspec.yaml?

Ответ

В файле pubspec.yaml зависимости разделяются на два типа, которые влияют на сборку приложения и процесс разработки.

dependencies (Основные зависимости):

Пакеты, необходимые для работы приложения в runtime. Они включаются в финальную сборку (APK, IPA, исполняемый файл).

dependencies:
  flutter:
    sdk: flutter

  # UI-библиотеки
  provider: ^6.1.2
  flutter_bloc: ^8.1.3

  # Работа с сетью
  dio: ^5.4.0

  # State management
  riverpod: ^2.4.9

  # Локальная база данных
  sqflite: ^2.3.0

  # Нативные возможности
  url_launcher: ^6.2.1
  camera: ^0.10.7

dev_dependencies (Зависимости для разработки):

Пакеты, нужные только в процессе разработки: тестирование, линтинг, кодогенерация, инструменты сборки. Не попадают в production-сборку.

dev_dependencies:
  flutter_test:
    sdk: flutter

  # Моки для тестов
  mockito: ^5.4.2
  mocktail: ^0.3.7

  # Генерация кода
  build_runner: ^2.4.7
  json_serializable: ^6.7.1
  freezed: ^2.4.7

  # Статический анализ
  flutter_lints: ^3.0.1

  # Инструменты
  flutter_gen_runner: ^5.4.0

  # Тестирование производительности
  integration_test:
    sdk: flutter

Практические примеры различий:

  1. Генерация кода:
    
    // Аннотация из json_serializable
    import 'package:json_annotation/json_annotation.dart';

part 'user.g.dart';

@JsonSerializable() class User { final String name; final int age;

User(this.name, this.age);

factory User.fromJson(Map<String, dynamic> json) => $UserFromJson(json); Map<String, dynamic> toJson() => $UserToJson(this); }


Запуск генерации (только в разработке):
```bash
flutter pub run build_runner build
  1. Тестирование:
    
    // test/widget_test.dart
    import 'package:flutter_test/flutter_test.dart';
    import 'package:mocktail/mocktail.dart';

class MockAuthService extends Mock implements AuthService {}

void main() { testWidgets('Login screen test', (tester) async { final mockAuth = MockAuthService(); when(() => mockAuth.login(any(), any())) .thenAnswer((_) async => User('test', 'token'));

await tester.pumpWidget(
  Provider<AuthService>.value(
    value: mockAuth,
    child: const LoginScreen(),
  ),
);

expect(find.text('Welcome'), findsOneWidget);

}); }



**Ключевые отличия:**

*   **Размер билда:** `dev_dependencies` не увеличивают размер production-приложения
*   **Время сборки:** Меньше зависимостей = быстрее компиляция release-версии
*   **Безопасность:** Код из `dev_dependencies` не выполняется у пользователей

**Мой workflow:** Я всегда разделяю зависимости и добавляю в `dev_dependencies` всё, что не нужно в рантайме. Это особенно важно для пакетов с нативным кодом, которые могут значительно увеличить размер приложения.

Ответ 18+ 🔞

А, ну это же классика, ёпта! Смотри, тут в pubspec.yaml вся движуха с зависимостями делится на два лагеря, как будто на вечеринке: одни — гости, которые останутся до утра и будут в финальном приложении, а другие — те, кто только на подготовке помогал и на саму тусовку не попал.

dependencies (Основные кореша, без которых приложение — просто труп):

Это те пакеты, без которых твоё приложение нихуя не запустится. Они вшиваются в итоговый билд — в тот самый APK или IPA, который пользователи качают.

dependencies:
  flutter:
    sdk: flutter

  # Для красоты и порядка
  provider: ^6.1.2
  flutter_bloc: ^8.1.3

  # Чтобы в интернет ходить
  dio: ^5.4.0

  # Управление состоянием, а то бардак будет
  riverpod: ^2.4.9

  # База данных локальная, чтоб данные не терялись
  sqflite: ^2.3.0

  # Штуки для нативных фич
  url_launcher: ^6.2.1
  camera: ^0.10.7

dev_dependencies (Инструменты и подсобные рабочие, которые только на стройплощадке нужны):

А это — наш спецназ для разработки. Тесты, генераторы кода, линтеры. В продакшн-сборку они не попадают, пользователь их нихуя не увидит. Представь, что это как бригада отделочников: после ремонта их нет, а результат их работы — есть.

dev_dependencies:
  flutter_test:
    sdk: flutter

  # Муляжи для тестов, чтобы на живых сервисах не экспериментировать
  mockito: ^5.4.2
  mocktail: ^0.3.7

  # Магия кодогенерации, чтоб руками JSON не разбирать
  build_runner: ^2.4.7
  json_serializable: ^6.7.1
  freezed: ^2.4.7

  # Статический анализ, или "умный дядька, который ругается на кривой код"
  flutter_lints: ^3.0.1

  # Разные утилиты
  flutter_gen_runner: ^5.4.0

  # Тесты интеграционные, чтоб всё приложение проверить
  integration_test:
    sdk: flutter

Ну и чтобы совсем понятно было, вот тебе живые примеры:

  1. Вот зачем нам эта кодогенерация, блядь:
    
    // Аннотация из json_serializable — она только на этапе разработки работает
    import 'package:json_annotation/json_annotation.dart';

part 'user.g.dart'; // Этот файл сгенерируется автоматом!

@JsonSerializable() class User { final String name; final int age;

User(this.name, this.age);

factory User.fromJson(Map<String, dynamic> json) => $UserFromJson(json); Map<String, dynamic> toJson() => $UserToJson(this); }


А чтобы эту магию запустить, в консоли пишешь команду, которая **только в разработке** работает:
```bash
flutter pub run build_runner build

И вуаля — user.g.dart появляется, а в прод-билде этого всего цирка нет.

  1. А вот как тесты с моками выглядят, ядрёна вошь:
    
    // test/widget_test.dart
    import 'package:flutter_test/flutter_test.dart';
    import 'package:mocktail/mocktail.dart';

// Насоздавали муляж сервиса авторизации class MockAuthService extends Mock implements AuthService {}

void main() { testWidgets('Тестируем экран логина', (tester) async { final mockAuth = MockAuthService(); // Подставляем фейковый ответ, чтобы не лезть в реальный бэкенд when(() => mockAuth.login(any(), any())) .thenAnswer((_) async => User('test', 'token'));

await tester.pumpWidget(
  Provider<AuthService>.value(
    value: mockAuth,
    child: const LoginScreen(),
  ),
);

// Проверяем, что всё отрендерилось как надо
expect(find.text('Welcome'), findsOneWidget);

}); }



**Итоговая разница, чтобы в голове отложилось:**

*   **Размер приложения:** Всё из `dev_dependencies` — не увеличивает итоговый билд. Пользователь не будет качать лишние 10 мегабайт твоих инструментов для тестов.
*   **Скорость сборки:** Релизная сборка компилируется быстрее, потому что не тащит за собой тонну вспомогательного хлама.
*   **Безопасность:** Код из `dev_dependencies` не выполняется на устройстве у тёти Маши из Воронежи. Никаких случайных утечек.

**Мой совет, чувак:** Привыкай сразу раскидывать зависимости по полочкам. Всё, что не нужно для работы приложения после установки — отправляй в `dev_dependencies`. Особенно это касается пакетов с нативным кодом — они могут раздуть твой билд так, что пользователи просто удалят приложение, не дождавшись загрузки. Доверия к таким сборкам — ноль ебать.