1. Зачем нужен Angular CLI для создания сервисов
В мире Angular есть две категории людей: те, кто любит делать всё вручную (создавать файлы, писать boilerplate-код, называть всё своими именами), и те, кто предпочитает, чтобы за них работал робот. Если вы относитесь ко второй категории (а это очень разумно!), Angular CLI — ваш лучший друг.
Angular CLI — это мощная утилита командной строки, которая помогает автоматизировать рутину: создавать компоненты, сервисы, модули, пайпы и многое другое. С помощью CLI можно не только сэкономить время, но и избежать типичных опечаток, ошибок в структуре файлов и других "человеческих" проблем.
Создание сервиса через CLI — это:
- Быстро.
- Безопасно (CLI не даст вам назвать файл не по правилам).
- Удобно (CLI сразу добавит нужные аннотации и boilerplate-код).
- Гарантирует, что ваш сервис будет совместим с системой DI Angular.
Синтаксис команды ng generate service
Для создания сервиса через CLI используется команда:
ng generate service имя_сервиса
или, что короче и чаще встречается:
ng g s имя_сервиса
Здесь:
- ng — это команда запуска Angular CLI.
- generate (или коротко g) — действие "создать".
- service (или коротко s) — тип создаваемого артефакта.
- имя_сервиса — имя вашего будущего сервиса (в формате kebab-case, то есть через дефис).
Пример:
ng generate service user
или
ng g s user
В результате Angular CLI создаст два файла:
user.service.ts— сам сервис.user.service.spec.ts— файл для unit-тестов (его можно не использовать, если вы пока не пишете тесты).
2. Как работает команда на практике
Давайте рассмотрим процесс пошагово на примере создания сервиса для работы с пользователями (user).
Запуск команды
Откройте терминал в корне вашего Angular-проекта и выполните:
ng g s user
Результат выполнения
В консоли вы увидите примерно следующее:
CREATE src/app/user.service.ts (138 bytes)
CREATE src/app/user.service.spec.ts (352 bytes)
В папке src/app/ появятся два новых файла. Если вы хотите, чтобы сервис лежал в поддиректории (например, services), укажите путь:
ng g s services/user
В результате файлы окажутся в src/app/services/.
Содержимое сгенерированного сервиса
Откройте файл user.service.ts. Вот что там будет по умолчанию:
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class UserService {
constructor() { }
}
Обратите внимание на аннотацию @Injectable с параметром { providedIn: 'root' }. Это значит, что сервис будет доступен как синглтон на уровне всего приложения (область видимости — "root"). Подробнее о разных областях видимости мы поговорим позднее, а пока просто помните: это самый частый и рекомендуемый вариант.
3. Параметры команды ng generate service
Angular CLI позволяет гибко настраивать создание сервисов с помощью различных параметров. Вот самые полезные из них:
--flat
По умолчанию CLI создаёт для сервиса отдельную папку (например, user/), а в ней — файлы сервиса и теста. Если вы хотите, чтобы файлы лежали прямо в указанной папке, используйте флаг --flat:
ng g s user --flat
Теперь файлы появятся в src/app/, а не в src/app/user/.
--skip-tests
Если вы не хотите создавать файл для тестов (например, пока вы не планируете их писать), добавьте флаг --skip-tests:
ng g s user --skip-tests
В этом случае будет создан только user.service.ts.
--module
Иногда бывает нужно, чтобы сервис автоматически регистрировался в определённом модуле (например, если вы не хотите использовать providedIn: 'root'). Для этого есть опция --module:
ng g s shared/logger --module=app
CLI попытается найти файл модуля (app.module.ts) и добавить туда ваш сервис (в секцию providers). Однако с появлением providedIn: 'root' это используется редко.
Все параметры
Посмотреть все доступные опции можно командой:
ng g s --help
4. Практика: создание сервиса для учебного приложения
Пусть в нашем учебном приложении есть список задач (tasks), и нам нужен сервис для работы с этим списком.
Создаём сервис
Выполните в терминале:
ng g s services/task --skip-tests
В результате появится файл src/app/services/task.service.ts со следующим содержимым:
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class TaskService {
constructor() { }
}
Добавляем методы в сервис
Давайте добавим простую реализацию хранения задач в памяти (да, в реальной жизни данные будут приходить с сервера, но для старта хватит и такого хранилища):
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class TaskService {
private tasks: string[] = [];
constructor() { }
getTasks(): string[] {
return this.tasks;
}
addTask(task: string) {
this.tasks.push(task);
}
removeTask(index: number) {
this.tasks.splice(index, 1);
}
}
Теперь сервис умеет возвращать список задач, добавлять и удалять задачи по индексу.
Используем сервис в компоненте
В каком-нибудь компоненте (например, task-list.component.ts), внедрите сервис через конструктор:
import { Component } from '@angular/core';
import { TaskService } from '../services/task.service';
@Component({
selector: 'app-task-list',
template: `
<ul>
<li *ngFor="let task of getTasks(); let i = index">
{{ task }}
<button (click)="removeTask(i)">Удалить</button>
</li>
</ul>
<input [(ngModel)]="newTask" placeholder="Новая задача">
<button (click)="addTask()">Добавить</button>
`
})
export class TaskListComponent {
newTask = '';
constructor(private taskService: TaskService) {}
getTasks() {
return this.taskService.getTasks();
}
addTask() {
if (this.newTask.trim()) {
this.taskService.addTask(this.newTask);
this.newTask = '';
}
}
removeTask(index: number) {
this.taskService.removeTask(index);
}
}
Внимание: Не забудьте подключить FormsModule в вашем модуле, чтобы работало двустороннее связывание через [(ngModel)].
5. Особенности и нюансы генерации сервисов через CLI
Именование сервисов
CLI всегда добавляет к имени файла суффикс .service.ts. Если вы создаёте сервис с именем user, файл будет называться user.service.ts а класс — UserService.
Структура папок
Рекомендуется группировать сервисы в отдельную папку (services/), особенно если их много. Это улучшает навигацию по проекту.
providedIn: 'root'
Сервис, созданный через CLI, по умолчанию становится синглтоном — один экземпляр на всё приложение. Если вы хотите, чтобы сервис был доступен только в определённом модуле, можно изменить параметр на providedIn: SomeModule или добавить сервис в секцию providers нужного модуля.
Автоматизация и масштабирование
CLI — это не только про скорость, но и про стандартизацию. Если в команде 5 разработчиков, CLI поможет всем создавать сервисы одинаково, без сюрпризов и "творческих" трактовок структуры файлов.
6. Типичные ошибки при создании сервисов через CLI
Ошибка №1: Неправильное имя сервиса.
CLI автоматически добавляет суффикс service. Если вы введёте ng g s user.service, получится файл user.service.service.ts, а это уже перебор даже для любителей многословности.
Ошибка №2: Не та папка.
Если запускать команду не из корня проекта, а из поддиректории, путь может оказаться неожиданным. Всегда проверяйте, где вы стоите перед запуском команды — или указывайте путь явно.
Ошибка №3: Забыли --skip-tests, а тесты не нужны.
CLI создаёт тестовый файл по умолчанию. Если вы не планируете его использовать, лучше сразу добавить флаг --skip-tests, чтобы не захламлять проект.
Ошибка №4: Ручное редактирование сгенерированного boilerplate-кода.
Не удаляйте аннотацию @Injectable или параметр providedIn: 'root', если не понимаете, зачем это делаете. Без этого Angular не сможет корректно внедрять сервис.
Ошибка №5: Несогласованность структуры.
Если часть сервисов лежит в src/app/, а часть — в src/app/services/, проект быстро превращается в лабиринт. Лучше выбрать одну стратегию и придерживаться её.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ