Создайте оптимизированное для SEO приложение Angular и разверните его на бессерверной платформе.
Вы можете создавать одностраничные приложения (SPA), оптимизированные для поисковых систем (SEO), с помощью Angular Universal, технологии, которая запускает ваше приложение Angular на сервере. Кроме того, вы можете снизить стоимость запуска этих приложений с помощью AWS Lambda, платформы бессерверных вычислений, управляемой событиями, предоставляемой как часть Amazon Web Services (AWS). В этом разделе показано, как создавать и развертывать проекты Angular Universal на AWS Lambda с помощью Serverless Framework, интерфейса командной строки с открытым исходным кодом для создания и развертывания бессерверных приложений.
В этой статье мы:
- Создайте приложение Angular, которое содержит два маршрута и выполняет вызовы внешнего API.
- Добавить рендеринг на стороне сервера для SEO
- Настроить конфигурацию фреймворка Serverless Framework
- Разверните приложение на AWS Lambda
Для выполнения этих задач вам необходимо создать учетную запись AWS и установить следующее:
- Node.js и npm (установка Node.js также установит npm.)
- Angular CLI
- AWS CLI
Для настройки интерфейса командной строки AWS вам потребуется следующее из вашей учетной записи AWS:
- Идентификатор ключа доступа
- Секретный ключ
- Регион по умолчанию
Ваш пользователь root будет иметь все права, необходимые для развертывания и запуска приложения Angular как функции Lambda. Вы можете получить идентификатор ключа доступа и секретный ключ для своего пользователя root, сгенерировав новую пару в консоли управления идентификацией и доступом (IAM).
Если вы не хотите использовать свой идентификатор пользователя root для этого проекта, вы можете настроить роль и политику IAM для API для вызова функций Lambda. Этот процесс состоит из нескольких этапов и не рекомендуется, если вы новичок в AWS.
Прежде чем продолжить, убедитесь, что вы успешно выполнили все эти задачи.
Настройте проект Angular и запустите Hello World!
Первый шаг, который мы должны сделать в каждом проекте Angular, - это инициализация и установка пакета:
ng new angularSeo --style css --routing false cd angularSeo
Внесем несколько небольших изменений в созданный проект. Во-первых, давайте добавим стиль к <app-root>
в src/index.html
файле. Замените существующий код следующим:
Затем замените существующее содержимое src/app/app.component.html
на:
<h1>Hello World!</h1>
Наконец, добавьте в src/styles.css
следующее:
Обратите внимание, что в приведенном выше примере мы используем мой любимый модный фон:
Загрузите его и поместите в src/assets/img
каталог.
Давайте запустим приложение, набрав:
ng serve
После открытия в вашем браузере вы должны увидеть:
Вы можете найти весь код до этого момента в репозитории GitHub, который вы можете клонировать:
git clone -b tutorial1_step1 https://github.com/maciejtreder/angular-seo.git angularSeo cd angularSeo/ npm install ng serve
Компоненты, маршрутизация и сервисы
Наше приложение пока не очень сложное. Давайте добавим к нему маршруты, компоненты и сервис:
ng g c first ng g c second ng g c menu ng g s echo
Хорошо, у нас много файлов. Начнем с src/app/first/first.component.ts
; это будет действительно просто. Замените содержимое по умолчанию следующим:
import { Component } from '@angular/core'; @Component({ template: '<h1>Hello World!</h1>' }) export class FirstComponent {}
Отредактируйте второй компонент src/app/second/second.component.ts
, который немного сложнее:
Примечание. Ваша среда разработки или линтер могут вызвать makeCall()
. Не беспокойтесь об этом: мы решим эту проблему ниже, когда создадим службу.
Здесь мы ввели несколько механизмов. Во-первых, это использование внешнего шаблона и внешнего стиля (templateUrl
и stylesUrls
). Angular дает нам возможность создавать шаблоны HTML и таблицы стилей CSS вне класса компонента.
Вот как должен выглядеть шаблон для второго компонента src/app/second/second.component.html
:
<h1>Second component</h1> <h2>This component injects EchoService</h2> Response is: <span>{{response | async | json}}</span>
И таблица стилей src/app/second/second.component.css
должна выглядеть так:
span { color: purple; display: block; background: #ccc; padding: 5px; }
Еще один механизм, который мы представили в этом компоненте, - это внедрение зависимостей. Если вы внимательно посмотрите на конструктор в second.component.ts
, вы увидите параметр типа EchoService
. Angular попытается инициализировать и передать объект типа EchoService
нашему классу SecondComponent
при его инициализации. Внедрение зависимостей - это метод, используемый для реализации архитектурной парадигмы, известной как инверсия управления (IoC).
Мы также ввели в шаблон Observable
тип и async
канал. Вы знакомы с Promises? Observable - это еще один шаг вперед. Этот асинхронный тип испускает значения, переданные ему другими функциями. Вы можете использовать его столько раз, сколько захотите, подписаться на нескольких слушателей и т. Д. (Сопоставление, фильтрация, переход к другому наблюдаемому и т. Д.). Подробнее об этом вы можете прочитать на странице RxJS GitHub.
Канал async в шаблоне second.component.html
- это специальный механизм Angular для отображения нашей переменной в шаблоне представления только при ее оценке. Другими словами, значение, помещенное в HTML во время выполнения, отправляется наблюдаемым EchoService
.
И последнее, но не менее важное: мы реализовали интерфейс OnInit
и ловушку жизненного цикла ngOnInit
. Интерфейсы в TypeScript работают так же, как интерфейсы в других языках; если вы его реализуете, вы должны реализовать все объявленные в нем методы. В этом конкретном случае нам нужно реализовать метод ngOnInit()
. Этот метод является одним из «крючков жизненного цикла Angular», методов, автоматически вызываемых движком Angular на разных этапах инициализации представления, уничтожения и других событий. Согласно документации Angular:
ngOnInit - Инициализирует директиву / компонент после того, как Angular сначала отобразит свойства с привязкой к данным и задает входные свойства директивы / компонента. Вызывается один раз, после первого
ngOnChanges()
.
Мы внедрили сервис во второй компонент. Теперь мы можем его создать. Замените содержимое по умолчанию src/app/echo.service.ts
следующим:
Эта служба содержит только один метод, который отправляет GET-запрос на https://jsonplaceholder.typicode.com/posts/1
URL.
Ok. Эта магия выглядит потрясающе, но вы, вероятно, спрашиваете: «Откуда Angular знает, что вводить, куда вводить и где инициализированы все эти классы?». Это отличные вопросы! Ответ: NgModule
, точка входа в наше приложение. Пора взглянуть на то, что внутри него происходит, и импортировать еще один модуль, необходимый для EchoService
: HttpClientModule
(src/app/app.module.ts
):
Что же мы имеем здесь..?
- Импорт - ссылки на другие
NgModules
- Объявления - список компонентов, используемых в приложении.
- Bootstrap - имя компонента, который мы хотим загрузить как «основной».
- Провайдеры - список сервисов, используемых в приложении.
Хорошо, теперь пора объявить маршрутизацию. Начнем с создания модуля маршрутизации:
ng generate module app-routing --flat --module=app
Теперь мы можем добавить наши маршруты в src/app/app-routing.module.ts
, экспортировать из него RouterModule
и удалить избыточный код (массив declarations
и импорт CommonModule
):
Мы можем добавить несколько ссылок в файл MenuComponent
, src/app/menu/menu.component.ts
:
Вы видите связь между routerLink
и маршрутами, объявленными в AppModule? Большой! Вот как мы связываем вещи в Angular: routerLink
- это встроенная директива Angular, которая принимает path
в качестве параметра и сопоставляет его с path
, объявленным в RouterModule.forRoot()
. Когда есть совпадение, он загружает данный компонент в <router-outlet>
компонент, который мы собираемся добавить в src/app/app.component.html
прямо сейчас. Замените код из этого файла на:
<app-menu></app-menu><router-outlet></router-outlet>
Наше приложение готово. Время запускать:
ng serve -o
Вот что вы должны увидеть в своем браузере:
Если вы нажмете кнопку «Второй компонент», вы увидите следующее, если все работает правильно:
Весь код до этого момента находится в этом репозитории GitHub, который вы можете клонировать:
git clone -b tutorial1_step2 https://github.com/maciejtreder/angular-seo.git angularSeo cd angularSeo/ npm install ng serve -o
Поисковая оптимизация (SEO)
Наше приложение выглядит готовым к развертыванию. Но есть некоторые проблемы, если мы «думаем» как сетевой сканер.
Запускаем наше приложение:
ng serve
Взгляните на наш сайт. Вы можете сделать это, проверив источник страницы или выполнив команду curl
ниже (если у вас установлен cURL):
В чем проблема? Как работают одностраничные приложения? Фактически, это чистый HTML с огромным количеством прикрепленных и выполняемых в браузере пользователя JavaScript.
Могут ли сканеры делать то же самое? GoogleBot может обрабатывать JavaScript, но другие сканеры (например, Facebook, LinkedIn, Twitter, Bing) - нет. Кроме того, веб-сайты, которые «выглядят» как статические и не ожидают от сканера дополнительных ресурсов для их чтения, занимают более высокие позиции в рейтинге поисковых систем из-за их более высокой производительности.
Как мы могли решить эту проблему? Это очень просто! Введите в командной строке следующее:
ng add @ng-toolkit/universal
Что сейчас произошло? @ ng-toolkit обновил наш проект функциональностью Angular Universal, технологией, которая запускает ваше приложение Angular на сервере. У нас есть пара новых файлов.
Изменения были внесены в файл src/app/app.module.ts
, который был точкой входа в наше приложение. @ Ng-toolkit удалил атрибут bootstrap
из аннотации @NgModule
, удалил BrowserModule
и добавил NgtUniversalModule
и CommonModule
в массив импорта.
Где сейчас загружается наше приложение? На самом деле, это зависит от обстоятельств. Если вы ищете начальную загрузку, используемую браузером, мы должны перейти к src/app/app.browser.module.ts
, вот где он находится:
@ Ng-toolkit также создал файл src/app/app.server.module.ts
. Это точка входа для кода, который будет выполняться на стороне сервера.
Теперь мы можем взглянуть на файл конфигурации проекта angular.json
. Мы обнаружим, что в наш проект добавлен новый конструктор.
(Многоточие («...
») в блоке кода указывает на раздел, отредактированный для краткости.)
Как видите, входным файлом для этой сборки является src/main.server.ts
, который также был добавлен в наш проект. Посмотрев на этот файл, мы можем определить точку входа, используемую компилятором Angular для создания сборки на стороне сервера:
Вот он: src/app/app.server.module.ts
, который представляет собой серверный рендеринг, эквивалентный src/app/app.browser.module.ts
, модулю, который загружает приложение для рендеринга в браузере.
Как вы, наверное, заметили, @ng-toolkit
также внес изменения в файл package.json
. У нас есть пара новых скриптов:
... "build:server:prod": "ng run angularSeo:server && webpack --config webpack.server.config.js --progress --colors", "build:browser:prod": "ng build --prod", "build:prod": "npm run build:server:prod && npm run build:browser:prod", "server": "node local.js" ...
Два самых важных находятся в конце списка:
build:prod
, который запускает компилятор Angular для сборок браузера и сервера, а затем создает файлserver.js
, используя конфигурацию Webpack, добавленную @ ng-toolkit.server
, который используется для запуска Node.js со скомпилированным приложением.
Попробуйте:
npm run build:prod npm run server
Мы можем попытаться вести себя как сетевой сканер:
curl localhost:8080
Бум! Если мы проверим источник страницы, мы увидим, что было сгенерировано на стороне сервера. Найдите ссылки, созданные для кнопок, показанных ниже:
Если вы не видите ожидаемых результатов или столкнулись с ошибкой, вы можете найти весь код до этого момента в этом репозитории GitHub, который вы можете клонировать:
git clone -b tutorial1_step3 https://github.com/maciejtreder/angular-seo.git angularSeo cd angularSeo/ npm install npm run build:prod npm run server
Развертывать!
Потрясающие! Наше приложение полностью разработано и оптимизировано для SEO. Мы готовы к развертыванию на 95%.
Обсудим оставшиеся 5%.
Обычно мы собираем наше приложение и публикуем все, что находится в папке dist
, на каком-нибудь хостинге (например, Amazon S3). «Проблема» в том, что мы ввели механизм рендеринга на стороне сервера, для которого требуется, чтобы Node.js работал на сервере. Нужен ли нам дорогостоящий инстанс EC2, работающий 24 часа в сутки?
Неа. Мы собираемся использовать AWS Lambda, среду Function as a Service (FaaS) вместе с Serverless Framework. Снова используя @ ng-toolkit, мы настроим базовую конфигурацию для Serverless Framework.
ng add @ng-toolkit/serverless
Эта команда создает файл serverless.yml
, который предоставляет конфигурацию для Serverless Framework, и файл lambda.js
, который обеспечивает точку входа для функции AWS Lambda. Он также вносит небольшие изменения в структуру.
Чтобы настроить проект для запуска в регионе AWS по умолчанию, отредактируйте файл serverless.yml
и замените значение region:
на имя региона AWS по умолчанию. Например, замените eu-central-1
на us-east-2
.
У нас также есть новые скрипты в package.json
. Воспользуйтесь одним из них:
Вы должны иметь возможность перейти к своему приложению по URL-адресу, указанному в выходных данных команды развертывания, как показано выше. URL-адрес будет включать ваш регион по умолчанию, если вы изменили значение в serverless.yml
.
Когда вы нажимаете кнопку «Второй компонент », результат должен выглядеть следующим образом:
В качестве последнего шага проверьте этот URL-адрес с помощью команды curl или проверив источник страницы:
Идеально. Наше приложение размещено в сети.
Вы можете найти весь код до этого момента в репозитории GitHub, который вы можете клонировать:
git clone -b tutorial1_step4 https://github.com/maciejtreder/angular-seo.git angularSeo cd angularSeo/ npm install npm run build:serverless:deploy
Резюме
Сегодня мы успешно разработали и развернули приложение Angular на AWS Lambda. Вы узнали, как вводить маршрутизацию, модули и сервисы в Angular, и все это с рендерингом на стороне сервера в целях оптимизации SEO. Эти методы позволяют развернуть приложение Angular в Интернете таким образом, чтобы он был доступен поисковым системам, при этом сводя к минимуму ваши эксплуатационные расходы. Используя AWS Lambda, вы платите только за время вычислений, необходимое для обслуживания запросов посетителей, вместо того, чтобы платить за каждую минуту, когда сервер находится в сети.
Ресурсы
Репозиторий GitHub: https://github.com/maciejtreder/angular-seo/tree/tutorial1_step4
Также посетите: https://github.com/maciejtreder/ng-toolkit, чтобы узнать о дополнительных возможностях Angular и Angular + Serverless Framework.
Вы также можете связаться со мной по адресу: [email protected] или @maciejtreder в GitHub, Twitter, StackOverflow и LinkedIn.