Целевая аудитория: сопровождающие CI в монорепозиториях, где фронтенд соседствует с iOS или React Native на пулах удалённого Mac — и где выбор Yarn Berry, PnP и зеркала registry упирается в трансграничную задержку и гигиену токенов. В 2026 году команды всё чаще фиксируют Node 22+ с Yarn 4.x через Corepack на Apple Silicon; спор не «какой Node новее», а что раньше ломает пайплайн — параллельная установка по сети или износ диска. Ниже — сравнительная таблица с поисковым интентом, копируемые параметры и FAQ. Без входа в аккаунт: главная MacPull, каталог блога; по соседству — sccache и ccache на удалённом Mac CI и зеркала провайдеров Terraform registry.

Трансграничная задержка: сравнение времени двух режимов (PnP и node_modules)

На хостинге удалённого Mac CI холодный yarn install упирается в TLS, RTT и объём tarball’ов, а не в локальный CPU. Yarn Berry с PnP (nodeLinker: pnp) снижает лавину мелких записей: один .pnp.cjs и сжатый .yarn/cache — часто выигрыш, когда зеркало registry далеко, а APFS быстрый. Классический node_modules (nodeLinker: node-modules) раздувает inode; он уместен, если инструменты ждут физические пути или postinstall уже переписывает дерево.

Режим Типичный выигрыш на удалённом Mac Трансграничный угол Ограничение гибридного monorepo
PnP Меньше метаданных после прогрева кеша; меньше файлов на фазе линковки Число tarball’ов как у node_modules; выигрыш после попадания пакетов в .yarn/cache Metro, Jest или iOS-скрипты могут потребовать sdk или linker node-modules точечно
node_modules Максимальная совместимость со «статом» глубоких деревьев Высокий RTT больнее при множестве мелких пакетов — жёстко настраивайте параллельную установку Предсказуемо для скриптов рядом с CocoaPods, ожидающих hoisted-пути
PnP + loose (компромисс) Смягчает строгую резолюцию для части пакетов Сетевой профиль близок к строгому PnP Зафиксируйте причину «loose» — security-ревью спросит

Ни один режим не отменяет близкое зеркало registry и HTTP/2-дружелюбный egress. Сравнивайте «PnP в 2 раза быстрее» только вместе с географией, числом хопов до зеркала и холодным/тёплым кешом.

Зеркало npm / Yarn: параметры .yarnrc.yml и сеть

Один источник правды для endpoint’ов registry. Для удалённого Mac CI согласуйте с security hostname зеркала и явные таймауты, чтобы job падал с ошибкой, а не «висел». Чеклист связывает Yarn 4 с операционным смыслом.

  1. npmRegistryServer — зеркало или апстрим по политике.
  2. networkConcurrency — потолок параллельной установки для трансграничных раннеров (старт 12–20, затем метрики).
  3. httpTimeout — худший случай tarball (часто 60–120 с на «шумных» линках).
  4. httpRetry — ограниченные повторы для 5xx/429 по внутренним правилам SRE.
  5. enableGlobalCache: true только на выделенных тёплых хостах с изоляцией тенантов.
  6. checksumBehavior в CI — throw, кроме аудируемых исключений.
# Фрагменты .yarnrc.yml — подставьте хосты; секреты не коммитить
nodeLinker: pnp          # или node-modules
compressionLevel: mixed

npmRegistryServer: "https://registry.npmmirror.com"  # пример зеркала

# Ограничить параллельные загрузки при высокой задержке
networkConcurrency: 16
httpTimeout: 90000
httpRetry: 3

# CI: упасть, если lockfile изменится
enableImmutableInstalls: true

# Опционально: глобальный кеш только на выделенных Mac mini
# enableGlobalCache: true

# Внутреннее зеркало без TLS — только с allowlist
# unsafeHttpWhitelist:
#   - "npm.internal.corp"

Сочетайте с Node 22+ и corepack enable, чтобы ноутбуки и агенты Apple Silicon брали одну линию yarnPath.

GitHub Packages и npm: двойная аутентификация и ротация токенов

Гибридные команды тянут публичное с npmjs, а приватные @org/* держат в GitHub Packages. В Yarn — npmScopes; токены только из переменных CI, не литералами в git. При ротации держите два перекрывающихся секрета минимум один цикл пайплайна: NPM_TOKEN и GITHUB_PACKAGES_TOKEN из vault.

# .yarnrc.yml — переменные окружения; значения в секретах CI
npmScopes:
  myorg:
    npmRegistryServer: "https://npm.pkg.github.com"
    npmAlwaysAuth: true
    npmAuthToken: "${GITHUB_PACKAGES_TOKEN}"

npmRegistries:
  "https://registry.npmjs.org":
    npmAuthToken: "${NPM_READ_TOKEN}"

Минимум прав: для install — read:packages на GitHub; публикация — отдельные workflow с узкими scope. Если зеркало registry в другой юрисдикции, согласуйте TLS-инспекцию и логирование с compliance — это не только latency.

Параллелизм CI, параллельная установка и пороги диска (watermark)

Параллельные job’ы умножают одновременные fetch tarball’ов. Ограничивайте и networkConcurrency, и лимиты оркестратора на узел. На диске node_modules в крупных monorepo легко десятки гигабайт; PnP смещает байты в .yarn/cache, но распаковка всё равно нужна. В runbook задайте три уровня: предупреждение (например свободно < 30 ГБ), троттлинг (не брать новые job), стоп (fail до порчи установки).

На общих пулах удалённого Mac коррелируйте алерты диска с фазой yarn install и Xcode DerivedData. Про кеш компиляции — матрица sccache и ccache; про смежные экосистемы — conda / mamba на удалённом Mac CI.

Повторы при сбоях, backoff и приёмка согласованности lockfile

Оборачивайте yarn install --immutable в ограниченный backoff (например 2, 4, 8 с) на транспортных ошибках, но не повторяйте вслепую нарушения checksum — это скрывает дрейф цепочки поставок. Ворота merge: одинаковый отпечаток yarn.lock на чистых macOS-агентах, отсутствие ошибок класса YN0028 на чистом checkout, зафиксированная версия Yarn в метаданных сборки.

#!/usr/bin/env bash
set -euo pipefail
corepack enable
corepack prepare yarn@stable --activate

attempt=1 max=4 delay=2
while [ "$attempt" -le "$max" ]; do
  echo "yarn install попытка $attempt/$max"
  if yarn install --immutable 2>&1 | tee "yarn-install-${attempt}.log"; then
    exit 0
  fi
  # Не повторять immutable / checksum (например YN0028)
  if grep -qE 'YN0028|checksumBehavior|checksum' "yarn-install-${attempt}.log"; then
    exit 1
  fi
  sleep "$delay"
  delay=$((delay * 2))
  attempt=$((attempt + 1))
done
exit 1

Флаки, которые проходят после перезапуска без кода, часто — лимиты зеркала registry, а не тесты; чините уровень registry раньше, чем jest.retryTimes на чужих шагах.

FAQ

По умолчанию PnP в новых monorepo в 2026? Да, если веб-стек поддерживает из коробки и нужно снять давление на inode на общих Mac; node-modules — если доминирует мобильный/нативный мост и нет бюджета на резолверы.

Ослабляет ли зеркало supply-chain? Только если отключать проверки целостности. Держите checksumBehavior: throw, зеркала только из allowlist, TLS зеркала — как у любого прокси зависимостей.

Связь с CocoaPods / SwiftPM? Стратегия JS независима, но конкурирует за диск и сеть на том же хосте — планируйте тяжёлый yarn install относительно prefetch нативных артефактов.

Смешивать linker’ы в одном репо? Yarn допускает dependenciesMeta точечно; документируйте — смешанный режим усложняет поддержку.

Итог

Yarn Berry и PnP выбирайте, когда inode и размер дерева дороже настройки резолвера; классический node_modules — когда совместимость дешевле, чем борьба с Metro и нативными скриптами. В обоих случаях удалённый Mac CI держится на управляемом зеркале registry, раздельных токенах npm и GitHub Packages, умеренной параллельной установке, порогах диска, неизменяемом lockfile и честных повторах без маскировки checksum.

Нужна предсказуемая очередь на Apple Silicon под Node 22+ и вашу схему зеркал — откройте страницу цен, покупку и аренду узла и центр помощи на macpull.com (читать можно без входа), начните с небольшого пула раннеров перед миграцией всего monorepo. Актуальные плейбуки — в каталоге блога рядом с материалами по registry и кешу.