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

Angular Universal

Angular Universal - это технология, позволяющая рендерить HTML-шаблоны на сервере. При этом само Angular приложение также исполняется на серверной стороне.

Генерация страниц может происходить и при запросе браузера, и в фоне, для последующей ее отдачи.

Создание приложения с использованием Angular Universal имеет следующие преимущества:

  • более эффективная работа поисковых роботов (SEO), поскольку они работают с уже сгенерированной страницей;
  • более быстрая работа приложения на мобильных и слабых по производительности устройствах.

Angular Universal приложение создается на основе модуля platform-server, обычное Angular приложение - на основе platform-browser.

Platform-server обрабатывает запрос, содержащий шаблон страницы, Angular модуль со всеми его компонентами и запрашиваемый URL с определяющим его компонентом. Результат обработки запроса - полностью сформированная HTML-страница для запрашиваемого URL.

Поскольку приложения, созданные с помощью Angular Universal, работают на сервере, а не в браузере, то они не могут обращаться к глобальным объектам браузера (например, window, navigation или location).

Таким образом, обработать события, инициированные пользователем (клик мыши, нажатие клавиши), также нельзя. Все, что можно делать - переходить по ссылкам.

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

Для начала работы необходимы следующие npm-модули:

  • @angular/platform-server - содержит необходимые для Angular Universal компоненты;
  • @nguniversal/module-map-ngfactory-loader - нужен для асинхронной загрузки;
  • @nguniversal/express-engine - ядро express фреймворка;
  • ts-loader - модуль для компиляции кода ts в js.

Теперь сразу рассмотрим пример, который можно скачать по ссылке.

Новыми здесь являются файлы app.server.module.ts, main.server.ts, server.ts, tsconfig.server.json, webpack.server.config.js.

Как видно из примера, Angular Universal мало чем отличается от обычного Angular приложения. Но есть моменты, на которые стоит обратить внимание.

Angular Universal работает только с абсолютными URL, клиентская часть - с относительными. Поэтому для корректной работы после перехода со статической версии необходимо использовать APP_BASE_HREF токен. Но такой вариант подойдет только если сервис API и само приложение находятся на одном и том же сервере. Иначе необходимо использовать функцию isPlatformBrowser().

Для определения текущей платформы (клиент или сервер), используется функция isPlatformBrowser(), которая принимает аргументом идентификатор платформы PLATFORM_ID. Идентификатор находится в библиотеке @angular/core.

Статические HTML-страницы. Для генерации страниц используется шаблонизатор Universal, настраиваемый в server.ts.

Web-сервер используется не только для отдачи статических файлов, но и принимает запросы на манипуляции с данными. Подобное разделение реализуется с помощью middleware (server.ts).

Конфигурация, описанная в tsconfig.server.json. В разделе compilerOptions тип модуля (свойство module) указывается как commonjs, а в разделе angularCompilerOptions необходимо указать путь к главному серверному модулю (здесь AppServerModule) в свойстве entryModule.

Важный момент - отдельная сборка серверной части Angular Universal приложения. Подробно изучите в разделе architect angular.json описание сборки с названием server.

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

ng build --prod && ng run {projectName}:server && webpack --config webpack.server.config.js --progress --colors

Первая часть команды - сборка клиентской части приложения, а вторая и третья - серверной, где {projectName} это имя вашего проекта, а server - имя конфигурации сборки проекта.

Далее можно запустить приложение.

node dist/server

Здесь указывается путь к директории с собранной серверной частью, который перед сборкой задается в свойстве outputPath конфигурации server.

Команда сборки слишком длинная, поэтому будет целесообразным добавить ее в package.json.