Вашему вниманию предлагается перевод туториала «5 min quickstart» от команды Angular. Туториал описывает процесс создания «Hello World»-приложения на новом фреймворке Angular 2, который недавно получил статус «бета».
Давайте начнём с нуля и построим суперпростое приложение Angular2 на TypeScript.
Демо
Запуск работающего примера — это самый лучший способ увидеть, как оживает приложение на Angular 2.
Нажатие этой ссылки открывает новую вкладку, загружает пример в plunker и отображает простое сообщение:
My First Angular 2 App
Вот файловая структура:
angular2-quickstart
├── app
│ ├── app.component.ts
│ └── boot.ts
├── index.html
└── license.md
Функционально это index.html и два файла TypeScript в папке app/. Давайте сделаем это!
Конечно, мы не будем создавать приложения, которые будут запускаться только в plunker. Давайте сделаем всё как если бы мы делали это в реальной жизни:
- Обустроим нашу среду разработки.
- Напишем корневой компонент Angular для нашего приложения.
- Загрузим его для того, чтобы он принял контроль над главной веб-страницей.
- Напишем главную страницу (index.html).
Мы действительно можем собрать QuickStart за пять минут, если будем следовать инструкциям и проигнорируем все комментарии.
Но многие из нас заинтересуются, «почему» и «как» всё это происходит, и ответ на эти вопросы займёт значительно больше времени.
Среда разработки
Нам необходимо место (папка проекта), несколько библиотек, некоторое количество настроек TypeScript и редактор с поддержкой TypeScript на ваш выбор.
Создадим новую папку нашего проекта
mkdir angular2-quickstart
cd angular2-quickstart
Добавим нужные нам библиотеки
Мы рекомендуем использовать менеджер пакетов npm для загрузки и управления библиотеками.
У вас нет npm? Установите его прямо сейчас, потому что мы будем использовать несколько раз на протяжении этого туториала.
Добавьте файл package.json в папку проекта и скопируйте в него следующий код:
// package.json
{
"name": "angular2-quickstart",
"version": "1.0.0",
"scripts": {
"tsc": "tsc",
"tsc:w": "tsc -w",
"lite": "lite-server",
"start": "concurrent "npm run tsc:w" "npm run lite" "
},
"license": "ISC",
"dependencies": {
"angular2": "2.0.0-beta.0",
"systemjs": "0.19.6",
"es6-promise": "^3.0.2",
"es6-shim": "^0.33.3",
"reflect-metadata": "0.1.2",
"rxjs": "5.0.0-beta.0",
"zone.js": "0.5.10"
},
"devDependencies": {
"concurrently": "^1.0.0",
"lite-server": "^1.3.1",
"typescript": "^1.7.3"
}
}
Не терпится узнать детали? Мы изложили их в приложении ниже.
Установите пакеты. Откройте окно терминала (командную строку в Windows) и запустите эту команду npm:
npm install
Жуткие красные сообщения об ошибках могут появиться в течение установки. Игнорируйте их. Установка будет успешной. Смотрите приложение ниже, если хотите узнать больше.
Сконфигурируем TypeScript
Нам необходимо довольно специфично настроить компилятор TypeScript.
Добавьте файл tsconfig.json в папку проекта и скопируйте в него следующее:
// tsconfig.json
{
"compilerOptions": {
"target": "ES5",
"module": "system",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": false
},
"exclude": [
"node_modules"
]
}
Мы исследуем tsconfig.json в приложении ниже.
Итак, всё готово. Давайте напишем немного кода.
Наш первый компонент Angular
Компонент(Component) — это наиболее фундаментальная концепция Angular. Компонент настраивает отображение(view) — часть веб-страницы, где мы показываем информацию пользователю и реагируем на его действия.
Технически, компонент — это класс, который контролирует шаблон отображения. Мы будем писать много таких классов при создании приложений Angular. Это наша первая попытка, так что мы сделаем всё предельно просто.
Создадим подпапку, в которой будут находиться исходники
Мы предпочитаем хранить код нашего приложения в подпапке под названием app/. Выполните следующую команду в консоли:
mkdir app
cd app
Добавим файл компонента
Теперь добавьте файл с именем app.component.ts и скопируйте в него следующий код:
// app/app.component.ts
import {Component} from 'angular2/core';
@Component({
selector: 'my-app',
template: '<h1>My First Angular 2 App</h1>'
})
export class AppComponent { }
Давайте подробно рассмотрим этот файл, начиная с самого конца, где мы определяем класс.
Класс Компонента
В самом низу файла располагается пустой и ничем не занятый класс под названием AppComponent. Когда мы будем готовы создать независимое приложение, мы сможем дополнить этот класс свойствами и логикой приложения. Наш класс AppComponent пуст, потому что нам не нужно, чтобы он что-то делал в этом QuickStart.
Модули
Приложения на Angular модульны. Они включают в себя множество файлов, каждый из которых имеет определённую цель.
Большинство файлов приложения экспортируют что-нибудь вроде компонента. Наш файл app.component экспортирует класс AppComponent.
// app/app.component.ts (export)
export class AppComponent { }
Факт экспорта превращает обыкновенный файл в модуль. Имя файла (без его расширения), как правило, является именем модуля. Таким образом, 'app.component' — это имя нашего первого модуля.
Более сложные приложения могут иметь дочерние компоненты, которые наследуют AppComponent в визуальном дереве. Более сложные приложения будут иметь больше файлов и модулей, как минимум столько, сколько у них есть компонентов.
QuickStart не сложен: один компонент — это всё, что нам нужно. Однако модули играют фундаментальную организационную роль даже в таком маленьком приложении.
Модули полагаются на другие модули. В приложениях Angular, написанных на TypeScript, когда нам нужно что-то, предоставляемое иным модулем, мы импортируем его. Когда другому модулю требуется сослаться на AppComponent, он импортирует символ AppComponent следующим образом:
// app/boot.ts
import {AppComponent} from './app.component'
Angular также является коллекцией библиотечных модулей. Каждая библиотека представляет собой модуль, составленный из нескольких связанных общим направлением модулей.
Если нам требуется что-то из Angular, мы импортируем это из его библиотечного модуля. И прямо сейчас нам нужно кое-что, чтобы иметь возможность определить метаданные для нашего компонента.
Метаданные компонента
Класс становится компонентом Angular, когда мы привязываем к нему метаданные. Angular нуждается в метаданных для того, чтобы понять, как нужно конструировать отображение, и как компонент взаимодействует с другими частями приложения.
Мы определяем метаданные компонента с помощью функции Component из Angular. Мы получаем доступ к этой функции, импортируя её из основной библиотеки Angular — angular2/core.
// app/app.component.ts (import)
import {Component} from 'angular2/core';
В TypeScirpt мы можем связать функцию и класс через превращение функции в декоратор. Для этого перед её названием нужно добавить символ @, и поместить её прямо перед объявлением класса.
// app/app.component.ts (metadata)
@Component({
selector: 'my-app',
template: '<h1>My First Angular 2 App</h1>'
})
@Component сообщает Angular, что данный класс является компонентом Angular. Объект конфигурации, отправляемый в @Component, имеет два поля: selector и template.
Свойство selector определяет обычный CSS селектор для HTML-элемента my-app, выступающего в качестве хоста. Angular создаёт и отображает экземпляр нашего AppComponent каждый раз, когда он сталкивается с my-app в родительском HTML.
Запомните селектор my-app! Нам будет нужна эта информация, когда мы будем писать наш index.html.
Свойство template содержит шаблон компонента. Шаблон — это разновидность HTML, которая объясняет Angular, как рендерить отображение. Наш шаблон — это единственная строка HTML, объявляющая: «My First Angular App».
Теперь нам нужно как-то объяснить Angular, что этот компонент необходимо загрузить.
Запустим его
Добавьте новый файл, boot.ts, в папку app/, и скопируйте в него следующий код:
// app/boot.ts
import {bootstrap} from 'angular2/platform/browser'
import {AppComponent} from './app.component'
bootstrap(AppComponent);
Нам требуются две вещи для того, чтобы запустить приложение:
- Браузерная функция Angular bootstrap.
- Корневой компонент приложения, который мы только что написали.
Мы импортируем и то, и другое. Потом мы вызываем bootstrap и передаём в неё тип корневого компонента AppComponent.
Изучить, почему мы импортируем bootstrap из angular2/platform/browser и почему мы создаём отдельный файл boot.ts, можно в приложении ниже.
Мы попросили Angular запустить приложение в браузере с нашим компонентом в качестве корневого. Однако, где же Angular его запустит?
Добавим страницу index.html
Angular отображает наше приложение в специфическом месте на нашей странице index.html. Пришло время создать этот файл.
Мы не будем класть index.html в папку app/. Мы расположим его на один уровень выше, в корневой папке проекта.
cd ..
Теперь создайте файл index.html и скопируйте в него следующее:
<!-- index.html -->
<html>
<head>
<title>Angular 2 QuickStart</title>
<!-- 1. Загрузите библиотеки -->
<script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="node_modules/rxjs/bundles/Rx.js"></script>
<script src="node_modules/angular2/bundles/angular2.dev.js"></script>
<!-- 2. Настройте SystemJS -->
<script>
System.config({
packages: {
app: {
format: 'register',
defaultExtension: 'js'
}
}
});
System.import('app/boot')
.then(null, console.error.bind(console));
</script>
</head>
<!-- 3. Отобразите приложение -->
<body>
<my-app>Loading...</my-app>
</body>
</html>
Здесь есть 3 секции HTML, которые необходимо отметить:
- Мы загружаем библиотеки JavaScript, которые нам требуются. angular2-polyfills.js и Rx.js требуются для работы Angular 2.
- Мы настраиваем нечто, что называется System, и просим его импортировать файл boot, который мы только что написали.
- Мы добавляем тэг <my-app> в <body>. Это то самое место, где обитает наше приложение!
Что-то должно найти и загрузить модули нашего приложения. Мы используем для этого SystemJS. Есть много вариантов, и нельзя сказать, что SystemJS — лучший выбор, но мы его любим, и он работает.
Специфика настройки SystemJS выходит за пределы данного туториала. Мы кратко опишем часть конфигурации в приложении ниже.
Когда Angular вызывает функцию bootstrap в boot.js, он читает метаданные AppComponent, находит селектор my-app, обнаруживает тэг с именем my-app и загружает наше приложение в этот тэг.
Скомпилируем и запустим!
Откройте окно терминала и введите следующую команду
npm start
Эта команда запускает два параллельных процесса node.
- Компилятор TypeScript в режиме наблюдения.
- Статический сервер lite-server, который загружает index.html в браузере и обновляет браузер каждый раз, когда код приложения изменяется.
В течение нескольких мгновений вкладка браузера должна открыться и отобразить:
My First Angular 2 App
Поздравляем! Вы в деле!
Если вы видите вместо этого Loading..., прочитайте приложение «Поддержка ES6 браузерами».
Внесём несколько изменений
Попробуйте изменить сообщение на «My SECOND Angular 2 app».
Компилятор TypeScript и lite-server наблюдают за вашими действиями. Они должны засечь изменение, перекомпилировать TypeScript в JavaScript, обновить вкладку браузера и отобразить обновлённое сообщение.
Это изящный способ разработки приложений!
Мы закрываем окно терминала когда мы всё сделали для того, чтобы прервать одновременно компилятор и сервер.
Финальная структура
Финальная структура нашей папки проекта должна выглядеть так:
angular2-quickstart
├── node_modules
├── app
│ ├── app.component.ts
│ └── boot.ts
├── index.html
├── package.json
└── tsconfig.json
И вот наши файлы:
import {Component} from 'angular2/core';
@Component({
selector: 'my-app',
template: '<h1>My First Angular 2 App</h1>'
})
export class AppComponent { }
import {bootstrap} from 'angular2/platform/browser'
import {AppComponent} from './app.component'
bootstrap(AppComponent);
<html>
<head>
<title>Angular 2 QuickStart</title>
<!-- 1. Загрузите библиотеки -->
<script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="node_modules/rxjs/bundles/Rx.js"></script>
<script src="node_modules/angular2/bundles/angular2.dev.js"></script>
<!-- 2. Настройте SystemJS -->
<script>
System.config({
packages: {
app: {
format: 'register',
defaultExtension: 'js'
}
}
});
System.import('app/boot')
.then(null, console.error.bind(console));
</script>
</head>
<!-- 3. Отобразите приложение -->
<body>
<my-app>Loading...</my-app>
</body>
</html>
{
"name": "angular2-quickstart",
"version": "1.0.0",
"scripts": {
"tsc": "tsc",
"tsc:w": "tsc -w",
"lite": "lite-server",
"start": "concurrent "npm run tsc:w" "npm run lite" "
},
"license": "ISC",
"dependencies": {
"angular2": "2.0.0-beta.0",
"systemjs": "0.19.6",
"es6-promise": "^3.0.2",
"es6-shim": "^0.33.3",
"reflect-metadata": "0.1.2",
"rxjs": "5.0.0-beta.0",
"zone.js": "0.5.10"
},
"devDependencies": {
"concurrently": "^1.0.0",
"lite-server": "^1.3.1",
"typescript": "^1.7.3"
}
}
{
"compileroptions": {
"target": "es5",
"module": "system",
"moduleresolution": "node",
"sourcemap": true,
"emitdecoratormetadata": true,
"experimentaldecorators": true,
"removecomments": false,
"noimplicitany": false
},
"exclude": [
"node_modules"
]
}
Заключение
Наше первое приложение делает не слишком много. Это, по сути, «Hello World» на Angular 2.
Для первого раза мы сделали всё максимально просто: написали небольшой компонент Angular, добавили немного библиотек JavaScript в index.html и запустили статический файловый сервер. В целом, это всё, что мы ожидали от «Hello World»-приложения.
У нас более серьёзные амбиции
Хорошая новость в том, что вся возня с установкой нас не касается. Возможно, мы чуть-чуть коснёмся package.json для обновления библиотек. Мы откроем index.html только если нам нужно будет добавить библиотеку или файл css-стилей.
Мы готовы к следующему шагу, и теперь наша задача — сконструировать приложение, которое демонстрирует, насколько великолепные вещи можно сделать с помощью Angular 2.
Присоединяйтесь к нам в туториале «Геройский тур»!
Приложения
Остаток данной главы посвящён набору приложений, более подробно излагающих кое-какие моменты, которые мы кратко затронули выше.
Здесь нет никакого критически важного материала. Читайте дальше, если вам интересны детали.
↑ Приложение: Поддержка ES6 браузерами
Angular 2 полагается на некоторые возможности стандарта ES2015, большая часть из которых уже включена в современные браузеры. Однако некоторым браузерам (таким, как IE11), требуются полифиллы (shim) для поддержки этой функциональности. Попробуйте загрузить следующие полифиллы перед другими скриптами в index.html:
<script src="node_modules/es6-shim/es6-shim.js"></script>
↑ Приложение: package.json
npm — это популярный менеджер пакетов для node, и многие Angular-разработчики используют его для загрузки и управления библиотеками, которые необходимы их приложениям.
Мы определили пакеты, которые нам необходимы в файле npm package.json.
Команда Angular предлагает использовать пакеты, указанные в секциях dependencies и devDependencies в этом файле:
// package.json (dependencies)
{
"dependencies": {
"angular2": "2.0.0-beta.0",
"systemjs": "0.19.6",
"es6-promise": "^3.0.2",
"es6-shim": "^0.33.3",
"reflect-metadata": "0.1.2",
"rxjs": "5.0.0-beta.0",
"zone.js": "0.5.10"
},
"devDependencies": {
"concurrently": "^1.0.0",
"lite-server": "^1.3.1",
"typescript": "^1.7.3"
}
}
Вы можете выбрать и другие пакеты. Мы рекомендуем именно этот набор потому, что знаем, что все его компоненты хорошо работают вместе. Подыграйте нам сейчас, а позже экспериментируйте в своё удовольствие, подбирая варианты, которые будут соответствовать вашим опыту и вкусу.
В package.json может присутствовать необязательная секция scripts, в которой мы можем определить полезные команды для выполнения разработки и построения. Мы включаем несколько таких скриптов в предлагаемом нами package.json:
// package.json (scripts)
{
"scripts": {
"tsc": "tsc",
"tsc:w": "tsc -w",
"lite": "lite-server",
"start": "concurrent "npm run tsc:w" "npm run lite" "
}
}
Мы уже видели, как можно запустить компилятор и сервер одновременно с помощью этой команды:
npm start
Мы исполняем скрипты npm в следующем формате: npm run + название-скрипта. Вот описание того, что делают скрипты:
- npm run tsc — запуск компилятора TypeScript на один проход
- npm run tsc:w — запуск компилятора TypeScript в режиме наблюдения; процесс продолжает работу, перекомпилируя проект в тот момент, когда засекает изменения, внесённые в файлы TypeScript.
- npm run lite — запускает lite-server, легковесный статический файловый сервер, написанный и поддерживаемый Джоном Папа с великолепной поддержкой приложений Angular, которые используют маршрутизацию.
↑ Приложение: Предупреждения и ошибки npm
Всё хорошо, когда любые консольные сообщения, начинающиеся с npm ERR! отсутствуют в конце работы npm install. Могут быть несколько сообщений npm WARN в течение работы команды — и это превосходный результат.
Мы часто наблюдаем сообщение npm WARN после серии gyp ERR! Игнорируйте его. Пакет может попытаться перекомпилировать себя с помощью node-gyp. Если эта попытка заканчивается неудачей, пакет восстанавливается (обычно на предыдущую версию), и всё работает.
Всё хорошо до тех пор, пока нет ни одного сообщения npm ERR! в самом конце npm install.
↑ Приложение: Конфигурация TypeScript
Мы добавили конфигурационный файл (tsconfig.json) в наш проект, чтобы объяснить компилятору, как нужно генерировать файлы JavaScript. Подробнее про tsconfig.json вы можете узнать из официальной TypeScript wiki.
Опции и флаги, которые мы добавили в файл, являются наиболее важными.
Хотелось бы немного подискутировать насчёт флага noImplicitAny. Разработчики TypeScript расходятся во мнении относительно того, должен он быть установлен как true или false. Здесь нет точного ответа, и мы всегда можем изменить флаг позже. Но наш выбор может серьёзно повлиять на крупные проекты, так что он достоин дискуссии.
Когда noImplicitAny установлен в позицию false, компилятор, если он не может вывести тип переменной в зависимости от того, как переменная используется, скрыто устанавливает тип переменной в any. Это и значит «скрытый (implicit) any».
Когда noImplicitAny установлен в позицию true, и компилятор TypeScript не может вывести тип, он всё ещё генерирует файл JavaScript, но также и отчитывается об ошибке.
В этом QuickStart и во многих других примерах этого Developer Guide мы устанавливаем noImplicitAny в позицию false.
Разработчики, которые предпочитают более строгую типизацию, должны устанавливать noImplicitAny в позицию true. Мы всё ещё можем установить тип переменной в позицию any, если это кажется наилучшим выбором, но мы должны сделать это явно после того, как немного поразмыслим над необходимостью этого шага.
Если мы устанавливаем noImplicitAny в true, мы можем также получить скрытые ошибки индексации. Если нам кажется, что это больше раздражает, чем помогает, мы можем выключить их с помощью следующего флага.
"suppressImplicitAnyIndexErrors":true
↑ Приложение: Конфигурация SystemJS
QuickStart использует SystemJS для загрузки приложения и библиотечных модулей. Однако не забывайте, что у него есть рабочие альтернативы, такие как высоко оцениваемый сообществом webpack. SystemJS — это неплохой выбор, но мы хотим дать ясное понимание, что это лишь выбор, а не предпочтение.
Все загрузчики модулей требуют конфигурирования, и любое конфигурирование загрузчика становится тем сложнее, чем более разнообразнее становится файловая структура — вплоть до того, что мы начинаем задумываться об объединении файлов для повышения производительности.
Мы рекомендуем вам хорошо разобраться в загрузчике, который вы выберете.
Узнать больше о конфигурации SystemJS можно здесь.
Приняв во внимание эти предостережения, что мы можем сделать?
<!-- index.html (Конфигурация SystemJS) -->
<script>
System.config({
packages: {
app: {
format: 'register',
defaultExtension: 'js'
}
}
});
System.import('app/boot')
.then(null, console.error.bind(console));
</script>
Узел packages указывает SystemJS, что делать, если он видит запрос на модуль из папки app/.
Наш QuickStart создаёт такие запросы каждый раз, когда в любом TypeScript-файле приложения обнаруживается подобный оператор импорта:
// boot.ts (часть)
import {AppComponent} from './app.component'
Обратите внимание, что наименование модуля (после from) не содержит расширения файла. Конфигурация packages задаёт SystemJS расширение по-умолчанию как 'js', то есть файл JavaScript.
Это разумно, потому что мы компилируем TypeScript в JavaScript прежде, чем запускать приложение.
В демо-примере на plunker мы компилируем в JavaScript прямо в браузере на лету. Это неплохо для демо, но это не может стать нашим выбором для разработки или релиза.
Мы рекомендуем компилировать в JavaScript в течение фазы построения перед тем, как запускать приложение, по нескольким причинам:
- Мы можем видеть ошибки и предупреждения времени компиляции, которые скрыты от нас в браузере.
- Прекомпиляция упрощает процесс загрузки модулей, да и намного проще найти проблему, когда компиляция является отдельным внешним процессом.
- Прекомпиляция даёт большую производительность, потому что браузеру нет нужды тратить время на компиляцию.
- Наша разработка движется быстрее, потому что мы всего лишь перекомпилируем изменившиеся файлы. Разница станет заметна, когда наше приложение будет содержать множество файлов.
- Прекомпиляция подходит беспрерывному процессу разработки — построению, тестам, деплою.
Вызов System.import заставляет SystemJS импортировать файл boot (boot.js… после компиляции boot.ts, помните?) boot — это файл, где мы просим Angular запустить приложение. Мы также отлавливаем и логируем ошибки запуска в консоль.
Все прочие модули загружаются с помощью запроса, который создаётся оператором импорта или самим Angular.
↑ Приложение: boot.ts
Загрузка платформоспецифична
Мы импортируем функцию bootstrap из angular2/platform/browser, не из angular2/core. Этому есть причина.
Мы можем назвать «ядром» только те возможности, которые одинаковы для всех целевых платформ. Действительно, многие приложения Angular могут быть запущены только в браузере, и мы будем вызывать функцию bootstrap из этой библиотеки наибольшее количество времени. Вполне «core»-фича — если мы пишем исключительно для браузера.
Но ведь вполне возможно загружать компонент в ином окружении. Мы можем загрузить его на мобильном устройстве с помощью Apache Cordova. Мы можем захотеть отрендерить начальную страницу нашего приложения на сервере для увеличения производительности или содействия SEO-продвижению.
Эти платформы требуют других вариантов bootstrap-функции, которые мы будем загружать из другой библиотеки
Зачем создавать отдельный файл boot.ts?
Файл boot.ts небольшой. Это всего лишь QuickStart. Мы вполне можем вписать эти несколько строк в файл app.component и избавить себя от излишней сложности.
Но мы так не делаем по причинам, которые, как мы верим, являются весомыми:
- Сделать всё правильно — это просто.
- Удобство тестирования.
- Удобство переиспользования.
- Разделение обязанностей.
- Изучение импорта и экспорта.
Это просто
Да, это дополнительный шаг и дополнительный файл. Насколько это сложно в целом?
Мы увидим, что отдельный файл boot.ts предпочтительней для большинства приложений — даже если это не столь важно для QuickStart. Давайте вырабатывать хорошие привычки сейчас, пока цена этому невысока.
Удобство тестирования
Мы должны думать об удобстве тестирования с самого начала, даже если мы знаем, что никогда не будем тестировать QuickStart.
Это сложно — тестировать компонент, когда в этом же файле присутствует функция bootstrap. Каждый раз, когда мы загружаем файл компонента для тестирования, функция bootstrap пытается загрузить приложение в браузере. Это вызывает ошибку, потому что мы не ожидали запуска целого приложения — лишь компонента.
Перемещение bootstrap-функции в boot.ts убирает ложную ошибку и оставляет нас с чистым файлом компонента.
Переиспользование
Мы рефакторим, переименовываем и перемещаем файлы в течение эволюции нашего приложения. Мы не сможем сделать ничего из этого, пока файл вызывает bootstrap. Мы не можем переместить его. Мы не можем переиспользовать компонент в другом приложении. Мы не можем отрендерить компонент на сервере для увеличения производительности.
Разделение обязанностей
Задача компонента — представлять отображение и управлять им.
Запуск приложения не имеет ничего общего с управлением отображением. Это совершенно другая обязанность. Проблемы, с которыми мы столкнулись при тестировании и переиспользовании, исходят именно из этого ненужного смешения обязанностей.
Импорт/Экспорт
Когда мы писали отдельный файл boot.ts, то получили важный навык для работы с Angular: как экспортировать что-то из одного модуля и импортировать в другой. Мы будем делать много подобного, когда будем более тесно работать с Angular.
Автор: Lodin