Перейти к содержанию

Ссылки на проекты

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

Благодаря ссылкам на проекты значительно сократилось время сборки проекта. В этом компилятору tsc помогают алгоритмы интеллектуальных инкрементальных сборок, которые компилируют только те части, которые в этом нуждаются. При этом под словом «часть» подразумевается не только фрагмент программы, но и отдельные проекты. Кроме того, ссылки на проекты после сборки повторяют исходную структуру связанных зависимостей, что немаловажно при работе с разбитыми на части проектами. Другими словами ссылки на проекты позволяют компилировать множество отдельных проектов, собираемых по правилам, описанным в уникальных для каждого проекта tsconfig.json, в результате чего будет получено множество завершенных частей программ (библиотеки, динамически подгружаемые части приложения, микросервисы). Добится подобного без использования ссылок на проекты невозможно, поскольку результатом обычной компиляции является только одна часть программы, собранная по правилам одного конфигурационного файла.

Проект, который использует другие проекты в качестве своих зависимостей, должен указать ссылки на них в своем конфигурационном файле. Для этих целей в tsconfig.json существует специальное свойство верхнего уровня references. Свойство references ассоциируется с массивом объектов, поля которого описывают установки для связываемых проектов. Одним из ключевых полей является path, в качестве значения которого указывается ссылка на конфигурационный файл tsconfig.json проекта-зависимости, либо директорию, которая его содержит.

{
  "references": [
    { "path": "path/to/tsconfig.json" },
    { "path": "path/to/dir/with/tsconfig-json/" }
  ]
}

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

{
  "compilerOptions": {
    "composite": true
  }
}

Данный флаг гарантирует активацию других параметров, необходимых для более эффективной и быстрой работы поиска зависимостей. Активация флага composite переопределяет некоторое стандартное поведение. Так, например, если параметр rootDir не установлен явно, то он будет ссылаться на директорию, содержащую конфигурационный файл tsconfig.json, в то время как обычно ссылается на директорию, из которой был запущен процесс компиляции.

При разработке с использованием загружаемых через npm сторонних библиотек в качестве источника информации о типах используются поставляемые в комплекте файлы декларации .d.ts. Разработчики могут быть в них уверены, так как после загрузки исходный код библиотек не изменяется. Когда в качестве зависимости выступает ссылка на проект, то изменение исходного кода является нормальной практикой. По этой причине, в качестве источников информации о типах используются сами файлы .ts или .tsx, составляющие эти проекты, поскольку только таким образом можно быть уверенным, что работа происходит с актуальной версией.

Если исходный код проектов, выступаемых в качестве зависимостей, не подвержен частым изменениям, то сборку проекта можно ускорить за счет установки значения false опции компилятора disableSourceOfProjectReferenceRedirect, что уведомит компилятор об исключении из наблюдения файлов проекта и указания в качестве источников типов файлов деклараций .d.ts. Данная опция указывается в конфигурационном файле проекта, выступающего в качестве зависимости. При этом нужно не забыть активировать саму генерацию деклараций, установив флаг declaration в true.

{
 "compilerOptions": {
   "disableSourceOfProjectReferenceRedirect": true,
   "declaration": true,
   "composite": true,

   "outDir": "path/to/outdir/"
 }

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

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

Команда компилятора --build ожидает перечисление конфигурационных файлов файлов и может быть использована совместно с такими специфичными для данной команды флагами, как --verbose, --dry, --clean и --force.

Флаг --verbose выводит подробную информацию о сборке и может сочетаться с любыми другими флагами. Флаг --dry выполняет сборку, не порождая выходные файлы. Флаг --clean удаляет выходные файлы, соответствующие заданным входным. --force принудительно выполняет не инкрементальную сборку. Кроме того, команда --build может сочетаться с такой командой как --watch, которая из всех специфичных для --build флагов сочетается только с флагом --verbose.

Также не лишним будет упомянуть, что при использовании команды --build компилятор ведет себя так, будто опция --noEmitOnError установлена в true. Причина этому инкрементальная сборка, которая, при наличии ошибки в коде, выводит уведомления только при непосредственной компиляции, которая возникает исключительно при условии внесения изменения в компилируемый граф зависимостей, что может привести к трудновыявляемым багам. Ведь если разработчик, при возникновении множества ошибок, первым делом возьмется за устранение ошибок, возникших в других зависимостях, об ошибках в коде, которого изменения не коснулись, компилятор сообщать уже не будет. Но несмотря на отсутствие ошибок в консоли, ошибки так и останутся в программе.