Irbisa · Шпаргалка

Пакеты и зависимости

Ограничения версий, pubspec.lock, разрешение версий, overrides, публикация, melos, апгрейды

Middle-разработчик · 19 вопросов

  1. 01

    Чем Dart-пакет отличается от Flutter-пакета и от Flutter-плагина?

    Dart-пакетом считается любая папка с pubspec.yaml; Flutter-пакетом называют пакет, зависящий от Flutter SDK; плагин представляет собой Flutter-пакет, который вдобавок несёт платформенный код (Kotlin, Java, Swift, Objective-C, C/C++), подключаемый к приложению при сборке.

    # A plugin's pubspec.yaml: the `plugin:` block is what makes it onename: battery_levelenvironment:  sdk: ^3.9.0  flutter: '>=3.35.0'…
  2. 02

    Чем отличаются dependencies, dev_dependencies и dependency_overrides в pubspec.yaml?

    В dependencies лежит то, что нужно вашему коду для работы, и это наследует каждый, кто зависит от вас; в dev_dependencies лежат инструменты для работы над самим пакетом (тесты, кодогенерация, линты), они не наследуются; dependency_overrides навязывают версию всему графу, и только в корневом пакете.

    dependencies:  dio: ^5.9.0  json_annotation: ^4.9.0     # lib/ imports the annotations dev_dependencies:  build_runner: ^2.5.0        # runs on your machine and in CI only…
  3. 03

    Нужно ли коммитить pubspec.lock и отличается ли ответ для приложения и для публикуемого пакета?

    Приложение всегда коммитит pubspec.lock.

  4. 04

    Чем отличаются pub get, pub upgrade и pub upgrade --major-versions?

    pub get берёт версии из pubspec.lock и разрешает только новое; pub upgrade заново подбирает самые свежие версии в рамках ваших ограничений; --major-versions вдобавок переписывает ограничения в pubspec.yaml, чтобы перейти через major.

    $ flutter pub outdated# Package         Current  Upgradable  Resolvable  Latest# dio             5.7.0    5.9.0       5.9.0       5.9.0# acme_analytics  1.9.4    1.9.6       2.3.0       2.3.0 $ flutter pub get                 # dio stays on 5.7.0: the lock wins…
  5. 05

    Какие версии pub может выбрать для каждого ограничения ниже и почему intl не берёт 0.21.0, а dio переезжает на 5.9.0?

    dependencies:  dio: ^5.7.0  intl: ^0.20.2  uuid: 4.5.1  web_socket_channel: '>=3.0.0 <3.0.3'  crypto: any

    Каретка разрешает всё до следующей ломающей версии, а ниже 1.0.0 ломающим считается minor: ^5.7.0 означает >=5.7.0 <6.0.0, а ^0.20.2 означает только >=0.20.2 <0.21.0.

  6. 06

    Каковы компромиссы hosted-, path- и git-зависимостей и когда допустимо указать ветку на GitHub?

    Hosted-зависимость задаёт диапазон версий, о котором солвер может договориться; path и git задают одну фиксированную версию, а пакет с любой из них нельзя опубликовать на pub.dev.

    dependencies:  dio: ^5.9.0                       # hosted on pub.dev   acme_domain:    path: ../packages/acme_domain   # inside this repo only…
  7. 07

    Как разделять приватные пакеты между несколькими приложениями компании?

    Либо git-зависимостями, закреплёнными на тегах (это не требует инфраструктуры), либо через приватный pub-репозиторий, который сохраняет полноценное разрешение версий.

    # The shared package: can only ever be published to the private servername: acme_uiversion: 3.2.0publish_to: https://pub.acme.internal ---…
  8. 08

    flutter pub get падает с «version solving failed» и длинной цепочкой «Because…». Как найти и исправить настоящий конфликт?

    Читайте снизу: последнее предложение называет ваш пакет и две зависимости, которые не уживаются, а первая строка Because называет общий пакет, о версии которого они спорят.

    $ flutter pub getBecause every version of flutter_localizations from sdk depends on intl 0.20.2  and acme_analytics >=2.1.0 depends on intl ^0.21.0, flutter_localizations  from sdk is incompatible with acme_analytics >=2.1.0.So, because checkout_app depends on both flutter_localizations from sdk  and acme_analytics ^2.1.0, version solving failed.…
  9. 09

    Что на самом деле отключает dependency_overrides и почему это крайняя мера?

    Он велит солверу использовать выбранную вами версию пакета везде в графе и игнорировать все ограничения, которые на него наложили другие пакеты, и pub get зеленеет на комбинации, которую никто не тестировал.

    dependencies:  acme_analytics: ^2.1.0      # needs intl ^0.21.0  flutter_localizations:    sdk: flutter              # pins intl exactly # wrong: pub get is green, the combination is untested…
  10. 10

    После обновления Flutter pub get падает с «requires SDK version >=2.7.0 <3.0.0» на чужом пакете. Что произошло и какие есть варианты?

    Диапазон environment: sdk: этого пакета исключает вашу версию Dart, и pub выбрасывает из разрешения все его версии.

  11. 11

    Ваш пакет на версии 1.2.0, и следующий релиз вносит три изменения ниже. Это patch, minor или major?

    // acme_toast 1.2.0, publishedclass Toast {  Toast({required this.message, this.seconds = 3});  final String message;  final int seconds;} enum ToastStyle { info, error } // Next release:// 1. Toast's constructor gains `required this.icon`.// 2. ToastStyle gains a third value, `warning`.// 3. A new top-level function `showToast(Toast toast)` is added.

    Major, 2.0.0: изменения 1 и 2 по отдельности могут сломать компиляцию кода потребителя, а это и есть определение ломающего изменения.

  12. 12

    Как структурировать, версионировать и опубликовать пакет на pub.dev и что уже нельзя отменить?

    Публичный API кладите в lib/, реализацию кладите в lib/src/, добавьте README.md, CHANGELOG.md, LICENSE и example/, запустите dart pub publish --dry-run, затем публикуйте.

    acme_result/  lib/    acme_result.dart     # public API: export 'src/result.dart' show Result;    src/      result.dart        # implementation, never imported by consumers  example/…
  13. 13

    Что меняют pub workspaces в монорепозитории и зачем ещё нужен Melos?

    Workspace (Dart 3.6+) превращает весь репозиторий в одно разрешение версий: один pubspec.lock, один pub get в корне и одна и та же версия каждой зависимости во всех пакетах.

    # pubspec.yaml at the repo rootname: acme_workspacepublish_to: noneenvironment:  sdk: ^3.9.0workspace:…
  14. 14

    Транзитивная зависимость, которую вы не выбирали, выпустила сломанный патч, и сборка начала падать. Что вы делаете первым делом?

    Проверьте, может ли это вообще до вас дойти: при закоммиченном pubspec.lock и CI с pub get --enforce-lockfile плохой релиз в апстриме ничего не меняет, пока кто-то сознательно не обновится.

    # 1) What moved, and who pulls it in?git diff HEAD~1 -- pubspec.lock | grep -A3 broken_jsonflutter pub deps --style=compact | grep broken_json # 2) Back to the last good resolutiongit checkout HEAD~1 -- pubspec.lock   # or the last known-good commit…
  15. 15

    Почему один плагин вроде path_provider разбит на pub.dev на несколько пакетов и от какого из них зависит ваше приложение?

    Это федеративный плагин: Dart API, платформенный интерфейс и реализация под каждую платформу живут в отдельных пакетах, поэтому платформу можно добавить или починить без владельца плагина.

    # bar_scanner/pubspec.yaml: the app-facing packagedependencies:  flutter: { sdk: flutter }  bar_scanner_platform_interface: ^2.0.0  bar_scanner_android: ^2.1.0        # endorsed: lands in every consumer  bar_scanner_ios: ^2.1.0…
  16. 16

    Двум пакетам в вашем pub workspace (или одному приложению) нужны разные major-версии одной зависимости. Почему pub не даст каждому свою копию и как выбраться?

    В Dart-программе есть ровно одна копия каждой библиотеки, определяемая её package: URI, поэтому pub выбирает одну версию каждого пакета на всё приложение.

  17. 17

    Команда обновляет зависимости дважды в год, и каждый раунд оборачивается днями тушения пожаров. Как сделать обновления рутиной?

    Вместо редких больших обновлений нужен ровный поток маленьких проверенных: бот каждую неделю открывает сгруппированные PR, CI проверяет каждый, а полное внимание человека нужно только для major-обновлений.

    # .github/dependabot.ymlversion: 2updates:  - package-ecosystem: pub    directory: /    schedule:…
  18. 18

    Как перевести приложение на новый релиз Flutter с ломающими изменениями?

    Обновляйтесь в отдельной ветке с версией, зафиксированной для всей команды, отдайте механические переименования dart fix --apply, затем пройдитесь по заметкам о breaking changes, анализатору, тестам и нативной сборке и выпускайте через бета-трек.

    # On a dedicated branch, with the version pinned for everyonefvm use 3.38.0               # writes .fvmrc; CI reads the same file fvm flutter pub upgrade      # plugins often need releases for the new SDKfvm flutter pub outdated…
  19. 19

    Ключевой для приложения пакет не выпускался два года и теперь блокирует обновление Dart SDK: форкнуть, завендорить или заменить?

    Сначала спрячьте пакет за своим интерфейсом, затем выбирайте по масштабу: замените его, если есть поддерживаемая альтернатива, завендорьте в packages/, если используете небольшую часть чистого Dart, или форкните через git: с закреплённым коммитом, если он нужен почти целиком, а замена слишком велика.