Angular CLI builders¶
28.02.2022
Ряд команд Angular CLI запускает сложные процессы в вашем коде, такие как линтинг, сборка или тестирование. Эти команды используют внутренний инструмент под названием Architect для запуска CLI builders, которые применяют другой инструмент для выполнения нужной задачи.
В версии 8 Angular API CLI Builder стал стабильным и доступным для разработчиков, которые хотят настроить Angular CLI, добавляя или изменяя команды. Например, вы можете поставить конструктор для выполнения совершенно новой задачи или изменить, какой сторонний инструмент используется существующей командой.
Этот документ объясняет, как билдеры CLI интегрируются с файлом конфигурации рабочего пространства, и показывает, как вы можете создать свой собственный билдер.
Найти код используемых здесь примеров можно в этом репозитории GitHub.
CLI builders¶
Внутренний инструмент Architect делегирует работу функциям-обработчикам, называемым builders. Функция-обработчик строителя получает два аргумента: набор входных опций
(объект JSON) и контекст
(объект BuilderContext
).
Разделение задач здесь такое же, как и в schematics, которые используются для других команд CLI, которые касаются вашего кода (например, ng generate
).
-
Объект
options
предоставляется пользователем CLI, а объектcontext
предоставляется API CLI Builder. -
В дополнение к контекстной информации, объект
context
, который является экземпляромBuilderContext
, также предоставляет доступ к методу планирования,context.scheduleTarget()
.Планировщик выполняет функцию-обработчик строителя с заданной целевой конфигурацией.
Функция-обработчик может быть синхронной (return a value) или асинхронной (return a Promise), или она может наблюдать и возвращать несколько значений (return an Observable). Возвращаемое значение или значения всегда должны быть типа BuilderOutput
.
Этот объект содержит булево поле success
и необязательное поле error
, которое может содержать сообщение об ошибке.
Angular предоставляет некоторые билдеры, которые используются в CLI для таких команд, как ng build
и ng test
. Целевые конфигурации по умолчанию для этих и других встроенных CLI-строителей можно найти (и настроить) в разделе "architect" файла конфигурации рабочего пространства, angular.json
.
Кроме того, расширяйте и настраивайте Angular, создавая свои собственные конструкторы, которые можно запустить с помощью команды ng run
CLI.
Структура проекта Builder¶
Builder находится в папке "project", которая по структуре похожа на рабочее пространство Angular, с глобальными конфигурационными файлами на верхнем уровне и более конкретной конфигурацией в папке с исходными кодами, определяющими поведение. Например, ваша папка myBuilder
может содержать следующие файлы.
Files | Purpose |
---|---|
src/my-builder.ts | Основной исходный файл для определения билдера. |
src/my-builder.spec.ts | Исходный файл для тестов. |
src/schema.json | Определение входных опций билдера. |
builders.json | Определение билдеров. |
package.json | Зависимости. См. https://docs.npmjs.com/files/package.json. |
tsconfig.json | TypeScript configuration. |
Опубликуйте конструктор в npm
(см. Публикация вашей библиотеки). Если вы опубликовали его как @example/my-builder
, установите его с помощью следующей команды.
1 |
|
Создание конструктора¶
В качестве примера создадим построитель, который копирует файл. Чтобы создать построитель, используйте функцию createBuilder()
CLI Builder и верните объект Promise<BuilderOutput>
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
Теперь давайте добавим к нему немного логики. Следующий код получает пути к исходному и целевому файлам из опций пользователя и копирует файл из исходного в целевой (используя Promise версию встроенной функции NodeJS copyFile()
).
Если операция копирования не удалась, возвращается ошибка с сообщением об основной проблеме.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
Обработка вывода¶
По умолчанию copyFile()
ничего не выводит на стандартный вывод процесса или в ошибку. Если возникает ошибка, может быть трудно понять, что именно пытался сделать билдер, когда возникла проблема.
Добавьте дополнительный контекст, записывая в журнал дополнительную информацию с помощью API Logger
.
Это также позволяет выполнять сам конструктор в отдельном процессе, даже если стандартный вывод и ошибки отключены (как в Electron app).
Вы можете получить экземпляр Logger
из контекста.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
|
Отчеты о ходе выполнения и состоянии¶
API CLI Builder включает в себя средства отчетов о ходе выполнения и состоянии, которые могут дать подсказки для определенных функций и интерфейсов.
Чтобы сообщить о ходе выполнения, используйте метод context.reportProgress()
, который принимает в качестве аргументов текущее значение, (необязательно) итог и строку состояния. Total может быть любым числом; например, если вы знаете, сколько файлов вам нужно обработать, total может быть числом файлов, а current должно быть числом обработанных на данный момент.
Строка состояния не изменяется, если вы не передадите новое значение строки.
Вы можете посмотреть пример того, как построитель tslint
сообщает о ходе работы.
В нашем примере операция копирования либо завершается, либо все еще выполняется, поэтому отчет о ходе выполнения не нужен, но вы можете сообщить о статусе, чтобы родительский билдер, вызвавший наш билдер, знал, что происходит. Используйте метод context.reportStatus()
для создания строки состояния любой длины.
Нет гарантии, что длинная строка будет показана полностью; она может быть обрезана в соответствии с пользовательским интерфейсом, который ее отображает.
Передайте пустую строку, чтобы удалить статус.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
Ввод конструктора¶
Вы можете вызвать конструктор косвенно через команду CLI или напрямую с помощью команды Angular CLI ng run
. В любом случае, вы должны предоставить необходимые входные данные, но можете позволить другим входным данным принимать значения по умолчанию, которые предварительно настроены для конкретной цели, предоставить предопределенную, именованную конфигурацию переопределения, а также предоставить дополнительные значения опций переопределения в командной строке.
Валидация входов¶
Вы определяете входные данные конструктора в схеме JSON, связанной с этим конструктором. Инструмент Architect собирает разрешенные входные значения в объект options
и проверяет их типы по схеме, прежде чем передать их в функцию builder.
(Библиотека Schematics делает аналогичную проверку пользовательского ввода.)
Для нашего примера конструктора, вы ожидаете, что значение options
будет JsonObject
с двумя ключами: source
и destination
, каждый из которых является строкой.
Вы можете предоставить следующую схему для проверки типов этих значений.
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Это очень простой пример, но использование схемы для валидации может быть очень мощным. Более подробную информацию можно найти на сайте JSON schemas website.
Чтобы связать реализацию нашего конструктора с его схемой и именем, необходимо создать файл builder definition, на который можно указать в package.json
.
Создайте файл с именем builders.json
, который будет выглядеть следующим образом:
1 2 3 4 5 6 7 8 9 |
|
В файл package.json
добавьте ключ builders
, который укажет инструменту Architect, где найти наш файл определения строителя.
1 2 3 4 5 6 7 8 9 10 |
|
Официальное имя нашего конструктора теперь @example/copy-file:copy
. Первая часть этого имени — это имя пакета (определяется с помощью разрешения узлов), а вторая часть — это имя билдера (определяется с помощью файла builders.json
).
Использование одной из наших опций
очень просто. Вы делали это в предыдущем разделе, когда обращались к options.source
и options.destination
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Конфигурация цели¶
Строитель должен иметь определенную цель, которая связывает его с определенной входной конфигурацией и проектом.
Цели определяются в файле angular.json
CLI configuration file. Цель определяет конструктор, который будет использоваться, его конфигурацию опций по умолчанию и названные альтернативные конфигурации.
Инструмент Architect использует определение цели для определения входных опций для данного запуска.
В файле angular.json
есть раздел для каждого проекта, и в разделе "architect" каждого проекта настраиваются цели для конструкторов, используемых командами CLI, такими как 'build', 'test' и 'lint'. По умолчанию, например, команда build
запускает конструктор @angular-devkit/build-angular:browser
для выполнения задачи сборки и передает значения опций по умолчанию, указанные для цели build
в файле angular.json
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
Команда передает сборщику набор опций по умолчанию, указанных в разделе "options". Если вы передадите флаг --configuration=production
, он использует значения переопределения, указанные в альтернативной конфигурации production
. Укажите дополнительные переопределения опций отдельно в командной строке.
Вы также можете добавить больше альтернативных конфигураций к цели build
, чтобы определить другие окружения, такие как stage
или qa
.
Целевые строки¶
Общая команда CLI ng run
принимает в качестве первого аргумента целевую строку следующего вида.
1 |
|
Детали | |
---|---|
project | Имя проекта Angular CLI, с которым связана цель. |
target | Именованная конфигурация построителя из секции architect файла angular.json . |
configuration | (optional) Имя конкретного переопределения конфигурации для данной цели, как определено в файле angular.json . |
Если ваш билдер вызывает другой билдер, ему может потребоваться прочитать переданную целевую строку. Разберите эту строку на объекты с помощью функции targetFromTargetString()
из @angular-devkit/architect
.
Планирование и запуск¶
Architect запускает билдеры асинхронно. Чтобы вызвать конструктор, вы планируете задачу, которая будет запущена после завершения разрешения всех конфигураций.
Функция построителя не выполняется, пока планировщик не вернет объект управления BuilderRun
. CLI обычно планирует задачи, вызывая функцию context.scheduleTarget()
, а затем разрешает входные параметры, используя определение цели в файле angular.json
.
Architect определяет входные параметры для заданной цели, беря объект опций по умолчанию, затем перезаписывая значения из используемой конфигурации\(если таковая имеется\), затем еще раз перезаписывая значения из объекта overrides, переданного в context.scheduleTarget()
. Для Angular CLI объект overrides строится из аргументов командной строки.
Architect проверяет полученные значения опций на соответствие схеме построителя. Если входные данные действительны, Architect создает контекст и выполняет построитель.
Дополнительные сведения см. в разделе Конфигурация рабочего пространства.
Вы также можете вызвать построитель непосредственно из другого построителя или теста, вызвав context.scheduleBuilder()
. Вы передаете объект options
непосредственно в этот метод, и значения опций проверяются на соответствие схеме построителя без дополнительной настройки.
Только метод context.scheduleTarget()
разрешает конфигурацию и переопределяет ее через файл angular.json
.
Конфигурация архитектора по умолчанию¶
Давайте создадим простой файл angular.json
, который вводит целевые конфигурации в контекст.
Вы можете опубликовать конструктор на npm (см. Публикация вашей библиотеки), и установить его с помощью следующей команды:
1 |
|
Если вы создадите новый проект с помощью ng new builder-test
, сгенерированный файл angular.json
будет выглядеть примерно так, только с конфигурациями билдера по умолчанию.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
|
Добавление цели¶
Добавьте новую цель, которая будет запускать наш конструктор для копирования файла. Эта цель указывает конструктору скопировать файл package.json
.
Необходимо обновить файл angular.json
, чтобы добавить цель для этого билдера в раздел "architect" нашего нового проекта.
-
Мы добавим новую целевую секцию в объект "architect" нашего проекта
-
Цель с именем "copy-package" использует наш конструктор, который вы опубликовали в
@example/copy-file
.(См. Публикация вашей библиотеки.)
-
Объект options предоставляет значения по умолчанию для двух входов, которые вы определили;
source
, который является существующим файлом, который вы копируете, иdestination
, путь, куда вы хотите скопировать. -
Ключ
configurations
является необязательным, мы его пока опустим.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
Запуск конструктора¶
Чтобы запустить наш конструктор с конфигурацией по умолчанию новой цели, используйте следующую команду CLI.
1 |
|
Это копирует файл package.json
в файл package-copy.json
.
Используйте аргументы командной строки для отмены настроенных значений по умолчанию. Например, для запуска с другим значением destination
используйте следующую команду CLI.
1 |
|
Это копирует файл в package-other.json
вместо package-copy.json
. Поскольку вы не переопределили параметр source, он будет скопирован из файла package.json
(значение по умолчанию, предоставленное для цели).
Тестирование билдера¶
Используйте интеграционное тестирование для вашего конструктора, чтобы вы могли использовать планировщик Architect для создания контекста, как в этом примере.
-
В каталоге исходных текстов построителя вы создали новый тестовый файл
my-builder.spec.ts
.Код создает новые экземпляры
JsonSchemaRegistry
(для валидации схемы),TestingArchitectHost
(реализация в памятиArchitectHost
), иArchitect
. -
Мы добавили файл
builders.json
рядом с файломpackage.json
сборщика и изменили файл пакета, чтобы он указывал на него.
Вот пример теста, который запускает конструктор копирования файлов. Тест использует конструктор для копирования файла package.json
и проверяет, что содержимое скопированного файла совпадает с исходным.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
|
При выполнении этого теста в вашем репозитории вам понадобится пакет ts-node
. Вы можете избежать этого, переименовав my-builder.spec.ts
в my-builder.spec.js
.
Режим наблюдения¶
Architect ожидает, что сборщики будут запущены один раз (по умолчанию) и возвращены. Такое поведение не совсем совместимо со сборщиком, который следит за изменениями (как Webpack, например).
Architect может поддерживать режим наблюдения, но есть некоторые моменты, на которые следует обратить внимание.
-
Чтобы использовать режим наблюдения, функция-обработчик билдера должна возвращать Observable.
Architect подписывается на Observable до его завершения и может повторно использовать его, если построитель будет запланирован снова с теми же аргументами.
-
После каждого выполнения построитель всегда должен выдавать объект
BuilderOutput
.После выполнения он может перейти в режим наблюдения, чтобы быть вызванным внешним событием.
Если событие вызывает его перезапуск, построитель должен выполнить функцию
context.reportRunning()
, чтобы сообщить Architect, что он снова запущен.Это не позволит Architect остановить построитель, если запланирован другой запуск.
Когда ваш билдер вызывает BuilderRun.stop()
для выхода из режима наблюдения, Architect отписывается от Observable билдера и вызывает логику разрушения билдера для очистки. (Это поведение также позволяет останавливать и очищать давно запущенные билды.)
В целом, если ваш билдер следит за внешним событием, вам следует разделить выполнение на три фазы.
Phases | Details |
---|---|
Выполнение | Например, webpack компилируется. Она заканчивается, когда webpack завершает работу и ваш билдер выдает объект BuilderOutput . |
Наблюдение | Между двумя запусками наблюдайте за внешним потоком событий. Например, webpack следит за изменениями в файловой системе. Это заканчивается, когда webpack перезапускает сборку, и вызывается context.reportRunning() . Это возвращает нас к шагу 1. |
Завершение | Либо задача полностью выполнена (например, webpack должен был запуститься несколько раз), либо выполнение сборки было остановлено (с помощью BuilderRun.stop() ). Ваша логика разрыва выполняется, и Architect отписывается от Observable вашего билдера. |
Резюме¶
API CLI Builder предоставляет новый способ изменения поведения Angular CLI с помощью билдеров для выполнения пользовательской логики.
- Конструкторы могут быть синхронными или асинхронными, выполняться однократно или следить за внешними событиями, и могут планировать другие конструкторы или цели.
-
Builders имеют параметры по умолчанию, указанные в конфигурационном файле
angular.json
, которые могут быть перезаписаны альтернативной конфигурацией для цели, а также флагами командной строки. -
Мы рекомендуем использовать интеграционные тесты для тестирования сборщиков Architect.
Используйте модульные тесты для проверки логики, которую выполняет билдер.
-
Если ваш построитель возвращает наблюдаемую величину, он должен очистить логику разрушения этой наблюдаемой величины.