Суть Читай реальные конфиги Turborepo и Nx, предсказывай task graph и поведение кэша и выбирай фикс с наибольшим рычагом.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на senior-высоте — в орбите
◷ 14 min
Конфиг пайплайна и ключ кэша — это места, где monorepo-проблемы реально диагностируются. Прочитай конфиг, предскажи task graph и то, что хэшируется в кэш, затем выбери фикс, который senior-инженер сделает первым.
Цель
Отработай цикл, который ты запускаешь на каждом медленном или небезопасном monorepo-пайплайне: прочти конфиг задач, выведи порядок и ключ кэша, замечай false hit или false miss и тянись к структурному фиксу раньше, чем добавлять железо.
Какой порядок даёт этот конфиг и в чём разница между двумя записями dependsOn?
Heads-up Каретка несущая. ^build = build-задача ЗАВИСИМОСТЕЙ этого пакета; build = build-задача ЭТОГО пакета. Убрав каретку, ты пропустишь сборку вышестоящих библиотек до приложения, которое их потребляет.
Heads-up ^build ограничен собственным поддеревом зависимостей текущего пакета, а не всем репозиторием. Turborepo обходит граф и упорядочивает только вышестоящие пакеты, от которых этот реально зависит.
Heads-up Пустые outputs значат, что нет файловых артефактов для восстановления, но задача всё равно кэшируется: попадание воспроизводит записанный успех и логи и пропускает повторный запуск. outputs перечисляет файлы для сохранения, а не факт кэширования.
Изменение в общем корневом tsconfig.json меняет вывод компилятора, но каждый build всё равно попадает в кэш и отдаёт устаревший dist. Читая эти inputs, в чём баг и фикс?
Heads-up outputs верны — dist это артефакт для сохранения и восстановления. Дефект на стороне ВХОДОВ: вход, меняющий вывод (tsconfig), отсутствует в хэше, поэтому ключ не меняется, когда должен.
Heads-up Порядок для build-задачи в норме; это проблема устаревшего вывода (false hit), а не порядка. Фикс — расширить inputs, чтобы покрыть каждый файл и инструмент, влияющий на скомпилированный вывод.
Heads-up Это выбрасывает всю выгоду кэша ради обхода одного отсутствующего входа. Senior-фикс — сделать ключ корректным (добавить tsconfig и toolchain в хэш), чтобы попадания оставались быстрыми И безопасными.
Сниппет 3 — affected-детекция
# CI: собрать/протестировать только то, что этот PR мог сломатьnpx nx affected -t build test --base=origin/main --head=HEAD
Викторина
Completed
На долгоживущей release-ветке эта команда вдруг сообщает, что для крошечного diff затронут весь репозиторий. Самая вероятная причина?
Heads-up affected детерминирован: это обход графа поверх git diff. Результат во весь репозиторий для малого изменения — сигнал, что diff (диапазон base/head) неверен, а не что алгоритм нестабилен.
Heads-up Scope affected вычисляется из git diff и графа проектов, полностью независимо от заполненности кэша. Полный кэш даёт промахи (пересборки), но никогда не раздувает affected-набор.
Heads-up Запуск нескольких целей в одном вызове affected нормален и задуман. Раздутый набор идёт от base-ревизии, охватывающей слишком большой diff, а не от объединения целей.
Какой импорт этот конфиг отклоняет на линте и какую проблему графа предотвращает отклонение?
Heads-up Это ребро явно РАЗРЕШЕНО: type:feature перечисляет type:ui в onlyDependOnLibsWithTags. Конфиг разрешает нисходящее направление feature → ui → util и отклоняет восходящие рёбра.
Heads-up enforce-module-boundaries роняет линт на нарушающем ребре зависимости. Это жёсткое ограничение на форму графа, а не предупреждение о стиле — именно это удерживает границы от размывания.
Heads-up util → util разрешён конфигом, поэтому именно это ребро проходит правило. Прямые циклы ловятся отдельно; этот сниппет отклоняет восходящее направление util → feature/ui.
Итог
Каждая проблема monorepo-пайплайна читается в конфиге и в git-диапазоне: каретка в dependsOn решает, собираются ли вышестоящие пакеты первыми; glob inputs — это ключ кэша, где отсутствующий tsconfig — false hit, а волатильный путь — false miss; scope affected — это обход графа поверх diff, поэтому неверный —base раздувает его до всего репозитория; а depConstraints не дают низкоуровневым библиотекам набрать fan-in, делающий каждое изменение глобальным. Прочти конфиг, почини ключ или границу, затем перезапусти и подтверди, что affected-набор и hit rate ведут себя верно.