Изолированные объявления TypeScript: ускорение сборки монорепозитория

Сборки монорепозиториев часто замедляются из-за того, как TypeScript обрабатывает файлы объявлений. По умолчанию TypeScript анализирует каждую цепочку импортов, прежде чем создать хотя бы один файл .d.ts. Это создает длинную очередь, в которой пакеты вынуждены ждать друг друга.

Это можно исправить с помощью флага --isolatedDeclarations.

Этот флаг позволяет выполнять сборку параллельно. Вместо ожидания зависимостей каждый пакет генерирует свои собственные объявления независимо. Команды отмечают ускорение сборки в 3–15 раз.

Проблема:

TypeScript обычно выводит типы через границы модулей. Если пакет A зависит от пакета B, компилятор должен полностью разрешить B, прежде чем приступить к A. В большом монорепозитории большинство пакетов простаивают, пока компилятор обрабатывает их по очереди.

Решение:

Флаг --isolatedDeclarations меняет правила. Он требует явного написания аннотаций типов для всего, что вы экспортируете.

Компромисс:

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

Результат:

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

Реальные результаты:

  • Монорепозиторий с 18 пакетами сократил время сборки с 47 секунд до 3,2 секунд.
  • В монорепозитории с 32 пакетами производительность в CI-конвейерах выросла в 8 раз.
  • Производительность масштабируется вместе с количеством ядер вашего процессора. Больше ядер — больше пакетов собираются одновременно.

Как перейти на этот режим:

  1. Включите флаг в корневом tsconfig.json и в конфигурации каждого пакета.
  2. Используйте флаг "composite", чтобы разрешить ссылки на проекты (project references).
  3. Добавляйте явные типы возвращаемых значений к экспортируемым функциям:
// До
export function add(a: number, b: number) {
  return a + b;
}

// После
export function add(a: number, b: number): number {
  return a + b;
}
  1. Добавляйте явные типы к экспортируемым константам:
// До
export const SETTINGS = { port: 3000 };

// После
export const SETTINGS: { port: number } = { port: 3000 };

Если вы не добавите эти типы, компилятор выдаст ошибку. Это гарантирует, что ваши типы будут детерминированными и быстрыми.

Источник: https://dev.to/jsmanifest/typescript-isolated-declarations-real-world-performance-gains-in-monorepo-build-times-25g3