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

Развертывание

📅 28.02.2022

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

Простые варианты развертывания

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

Сборка и обслуживание с диска

Во время разработки вы обычно используете команду ng serve для сборки, просмотра и обслуживания приложения из локальной памяти, используя webpack-dev-server. Однако, когда вы готовы к развертыванию, вы должны использовать команду ng build для сборки приложения и развертывания артефактов сборки в другом месте.

И ng build, и ng serve очищают выходную папку перед сборкой проекта, но только команда ng build записывает сгенерированные артефакты сборки в выходную папку.

По умолчанию папкой вывода является dist/project-name/. Для вывода в другую папку измените outputPath в файле angular.json.

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

  • На первом терминале выполните команду ng build в режиме watch для компиляции приложения в папку dist.

    1
    ng build --watch
    

    Как и команда ng serve, эта команда регенерирует выходные файлы при изменении исходных файлов.

  • На втором терминале установите веб-сервер (например, lite-server), и запустите его в папке output.

    Например:

    1
    lite-server --baseDir="dist/project-name"
    

    Сервер будет автоматически перезагружать ваш браузер при выводе новых файлов.

Этот метод предназначен только для разработки и тестирования и не является поддерживаемым или безопасным способом развертывания приложения.

Автоматическое развертывание с помощью CLI

Команда Angular CLI ng deploy (введена в версии 8.3.0) выполняет deploy CLI builder, связанный с вашим проектом. Ряд сторонних билдеров реализуют возможности развертывания на различных платформах.

Вы можете добавить любой из них в свой проект, выполнив команду ng add [имя пакета].

Когда вы добавите пакет с возможностью развертывания, он автоматически обновит конфигурацию вашего рабочего пространства (файл angular.json) с секцией deploy для выбранного проекта. Затем вы можете использовать команду ng deploy для развертывания этого проекта.

Например, следующая команда автоматически развертывает проект на Firebase.

1
2
ng add @angular/fire
ng deploy

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

Команда создает ваше приложение и загружает производственные активы в Firebase.

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

Вы можете узнать больше, перейдя по ссылкам, связанным с названиями пакетов ниже:

Развертывание на Пакет
Firebase hosting @angular/fire
Vercel vercel init angular
Netlify @netlify-builder/deploy
GitHub pages angular-cli-ghpages
NPM ngx-deploy-npm
Amazon Cloud S3 @jefiozie/ngx-aws-deploy

Если вы развертываете на самоуправляемом сервере или для вашей любимой облачной платформы нет конструктора, вы можете либо создать конструктор, который позволит вам использовать команду ng deploy, либо прочитать это руководство, чтобы узнать, как вручную развернуть ваше приложение.

Базовое развертывание на удаленном сервере

Для простейшего развертывания создайте производственную сборку и скопируйте выходной каталог на веб-сервер.

  1. Начните с производственной сборки:

    1
    ng build
    
  2. Скопируйте все в выходную папку (dist/project-name/ по умолчанию) в папку на сервере.

  3. Настройте сервер на перенаправление запросов на недостающие файлы на index.html.

    Узнайте больше о перенаправлениях на стороне сервера ниже.

Это самое простое развертывание вашего приложения, готовое к производству.

Развертывание на GitHub Pages

Чтобы развернуть ваше приложение Angular на GitHub Pages, выполните следующие шаги:

  1. Создайте репозиторий GitHub для вашего проекта.

  2. Настройте git в локальном проекте, добавив remote, указывающий на репозиторий GitHub, который вы создали на предыдущем шаге. GitHub предоставляет эти команды при создании репозитория, чтобы вы могли скопировать и вставить их в командную строку. Команды должны быть похожи на следующие, хотя GitHub заполняет за вас настройки, специфичные для вашего проекта:

    1
    2
    3
    git remote add origin https://github.com/your-username/your-project-name.git
    git branch -M main
    git push -u origin main
    

    Когда вы вставляете эти команды из GitHub, они выполняются автоматически.

  3. Создайте и проверьте ветку git с именем gh-pages.

    1
    git checkout -b gh-pages
    
  4. Соберите проект, используя имя проекта GitHub, с помощью команды Angular CLI ng build и следующих опций, где your_project_name — это имя проекта, которое вы дали репозиторию GitHub на шаге.

    Не забудьте включить косые черты по обе стороны от имени вашего проекта, как в /your_project_name/.

    1
    ng build --output-path docs --base-href /your_project_name/
    
  5. Когда сборка будет завершена, создайте копию docs/index.html и назовите ее docs/404.html.

  6. Зафиксируйте свои изменения и запустите.

  7. На странице проекта на GitHub перейдите в раздел Settings и выберите опцию Pages на левой боковой панели, чтобы настроить сайт на публикацию из папки docs.

  8. Нажмите Сохранить.

  9. Нажмите на ссылку GitHub Pages в верхней части раздела GitHub Pages, чтобы увидеть ваше развернутое приложение. Формат ссылки — https://<имя_пользователя>.github.io/<имя_проекта>.

Посмотрите angular-cli-ghpages, полнофункциональный пакет, который делает все это за вас и имеет дополнительную функциональность.

Конфигурация сервера

В этом разделе рассматриваются изменения, которые вам, возможно, придется внести в сервер или в файлы, развернутые на сервере.

Маршрутизируемые приложения должны возвращаться к index.html

Ангулярные приложения — идеальные кандидаты для обслуживания с помощью простого статического HTML-сервера. Вам не нужен движок на стороне сервера для динамической компоновки страниц приложения, потому что

Angular делает это на стороне клиента.

Если приложение использует маршрутизатор Angular, вы должны настроить сервер так, чтобы он возвращал страницу хоста приложения (index.html) при запросе файла, которого у него нет.

Маршрутизируемое приложение должно поддерживать "глубокие ссылки". Глубокая ссылка — это URL, указывающий путь к компоненту внутри приложения.

Например, http://www.mysite.com/heroes/42 — это глубокая ссылка на страницу детализации героя, которая отображает героя с id: 42.

Нет никаких проблем, когда пользователь переходит по этому URL из запущенного клиента. Маршрутизатор Angular интерпретирует URL и направляет на эту страницу и героя.

Но щелчок по ссылке в электронном письме, ввод в адресной строке браузера или просто обновление браузера на странице с подробной информацией о герое — все эти действия обрабатываются самим браузером, вне запущенного приложения. Браузер делает прямой запрос к серверу для этого URL, минуя маршрутизатор.

Статический сервер обычно возвращает index.html, когда получает запрос http://www.mysite.com/. Но он отвергает http://www.mysite.com/heroes/42 и возвращает ошибку 404 — Not Found, если только он не настроен на возврат index.html вместо этого.

Примеры конфигурации Fallback

Не существует единой конфигурации, подходящей для каждого сервера. В следующих разделах описаны конфигурации для некоторых наиболее популярных серверов.

Этот список ни в коем случае не является исчерпывающим, но должен послужить вам хорошей отправной точкой.

Apache

Добавьте правило перезаписи в файл .htaccess, как показано (ngmilk.rocks/2015/03/09/angularjs-html5-mode-or-pretty-urls-on-apache-using-htaccess):

1
2
3
4
5
6
7
8
RewriteEngine On
  # If an existing asset or directory is requested go to it as it is
  RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
  RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
  RewriteRule ^ - [L]

  # If the requested resource doesn't exist, use index.html
  RewriteRule ^ /index.html

Nginx

Используйте try_files, как описано в Front Controller Pattern Web Apps, модифицированный для обслуживания index.html:

1
try_files $uri $uri/ /index.html;

Ruby

Создайте Ruby-сервер с помощью (sinatra) с базовым Ruby-файлом, конфигурирующим сервер server.rb:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
require 'sinatra'

# Folder structure
# .
# -- server.rb
# -- public
#    |-- project-name
#        |-- index.html

get '/' do
  folderDir = settings.public_folder + '/project-name'  # ng build output folder
  send_file File.join(folderDir, 'index.html')
end

IIS

Добавьте правило перезаписи в web.config, аналогичное показанному здесь:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<system.webServer>
  <rewrite>
    <rules>
      <rule name="Angular Routes" stopProcessing="true">
        <match url=".*" />
        <conditions logicalGrouping="MatchAll">
          <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
          <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
        </conditions>
        <action type="Rewrite" url="/index.html" />
      </rule>
    </rules>
  </rewrite>
</system.webServer>

GitHub Pages

Вы не можете напрямую настроить сервер GitHub Pages, но вы можете добавить страницу 404. Скопируйте index.html в 404.html. Она по-прежнему будет передаваться как ответ 404, но браузер обработает эту страницу и загрузит приложение должным образом. Также хорошей идеей будет обслуживать из docs на main и создать файл .nojekyll.

Firebase hosting

Добавьте правило rewrite.

1
2
3
4
"rewrites": [ {
  "source": "**",
  "destination": "/index.html"
} ]

Настройка правильного MIME-типа для JavaScript-активов

Все файлы JavaScript вашего приложения должны обслуживаться сервером с заголовком Content-Type, установленным на text/javascript или другой JavaScript-совместимый MIME-тип.

Большинство серверов и хостинговых служб уже делают это по умолчанию.

Сервер с неправильно настроенным mime-типом для файлов JavaScript приведет к тому, что приложение не запустится со следующей ошибкой:

1
Failed to load module script: The server responded with a non-JavaScript MIME type of "text/plain". Strict MIME type checking is enforced for module scripts per HTML spec.

Если это так, вам необходимо проверить конфигурацию вашего сервера и перенастроить его на обслуживание файлов .js с Content-Type: text/javascript. Инструкции о том, как это сделать, см. в руководстве по эксплуатации вашего сервера.

Запрос услуг с другого сервера (CORS)

Разработчики Angular могут столкнуться с ошибкой cross-origin resource sharing, когда делают запрос сервиса (обычно запрос сервиса данных) на сервер, отличный от собственного сервера приложения. Браузеры запрещают такие запросы, если только сервер не разрешает их явно.

Клиентское приложение ничего не может сделать с этими ошибками. Сервер должен быть настроен на прием запросов приложения.

О том, как включить CORS для определенных серверов, читайте на enable-cors.org.

Оптимизация производства

Конфигурация production задействует следующие возможности оптимизации сборки.

Features Details
Ahead-of-Time (AOT) Compilation Предварительная компиляция шаблонов компонентов Angular.
Производственный режим Оптимизирует приложение для наилучшей производительности во время выполнения
Пакетирование Конкатенирует множество файлов приложения и библиотек в несколько пакетов.
Минификация Удаляет лишние пробельные символы, комментарии и необязательные лексемы.
Углификация Переписывает код для использования коротких, загадочных имен переменных и функций.
Устранение мертвого кода Удаление модулей без ссылок и много неиспользуемого кода.

См. ng build для получения дополнительной информации о параметрах сборки CLI и о том, что они делают.

Режим разработки во время выполнения

Когда вы запускаете приложение локально с помощью ng serve, Angular использует конфигурацию режима разработки во время выполнения. Режим разработки во время выполнения позволяет использовать дополнительные проверки безопасности, более подробные сообщения об ошибках

и отладочные утилиты, такие как обнаружение expression-changed-after-checked. Angular выводит

сообщение в консоль браузера, чтобы показать, что режим разработки включен.

Эти дополнительные проверки полезны при разработке, но они требуют дополнительного кода в связке, что нежелательно в продакшене. Чтобы гарантировать отсутствие последствий для размера пакета, оптимизатор сборки

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

Сборка приложения с конфигурацией production автоматически включает производственный режим выполнения Angular.

Ленивая загрузка

Вы можете значительно сократить время запуска, загружая только те модули приложения, которые абсолютно точно должны присутствовать при запуске приложения.

Настройте Angular Router на отложенную загрузку всех остальных модулей (и связанного с ними кода), либо дожидаясь запуска приложения, либо lazy loading по требованию.

Не импортируйте с нетерпением что-то из лениво загруженного модуля

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

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

Пакеты не знают о конфигурации маршрутизатора и не могут создавать отдельные пакеты для модулей с ленивой загрузкой.

Вам придется создавать эти пакеты вручную.

CLI запускает Angular Ahead-of-Time Webpack Plugin, который автоматически распознает лениво загруженные NgModules и создает для них отдельные пакеты.

Измерение производительности

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

Вы можете потратить много времени и денег на оптимизацию того, что не принесет ощутимой пользы или даже сделает приложение медленнее.

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

Страница Chrome DevTools Network Performance — хорошее место для начала изучения измерения производительности.

Инструмент WebPageTest — еще один хороший выбор, который также поможет убедиться, что развертывание прошло успешно.

Инспектирование пакетов

Инструмент source-map-explorer — это отличный способ проверить сгенерированные JavaScript-пакеты после сборки.

Установите source-map-explorer:

1
npm install source-map-explorer --save-dev

Создайте свое приложение для производства включая карты исходных текстов.

1
ng build --source-map

Перечислите созданные пакеты в папке dist/project-name/.

1
ls dist/project-name/*.js

Запустите проводник, чтобы создать графическое представление одного из пучков. В следующем примере показан график для пакета main.

1
node_modules/.bin/source-map-explorer dist/project-name/main*

source-map-explorer анализирует карту исходных текстов, созданную с помощью пакета, и рисует карту всех зависимостей, показывая, какие именно классы включены в пакет.

Вот результат для пакета main примера приложения под названием cli-quickstart.

quickstart sourcemap explorer

Тег base

HTML <base href="..." /> определяет базовый путь для преобразования относительных URL-адресов к таким ресурсам, как изображения, скрипты и таблицы стилей. Например, учитывая <base href="/my/app/">, браузер преобразует URL, такой как some/place/foo.jpg, в запрос сервера для my/app/some/place/foo.jpg.

Во время навигации маршрутизатор Angular использует base href в качестве базового пути к файлам компонентов, шаблонов и модулей.

См. также альтернативу APP_BASE_HREF.

При разработке вы обычно запускаете сервер в папке, содержащей index.html. Это корневая папка, и вы добавляете <base href="/"> в начало index.html, потому что / — это корень приложения.

Но на общем или рабочем сервере вы можете обслуживать приложение из вложенной папки. Например, если URL для загрузки приложения имеет вид http://www.mysite.com/my/app, то подпапка будет my/app/, и вы должны добавить <base href="/my/app/"> в серверную версию index.html.

Когда тег base неправильно настроен, приложение не загружается, и в консоли браузера появляются ошибки 404 — Not Found для отсутствующих файлов. Посмотрите, где он пытался найти эти файлы, и настройте тег base соответствующим образом.

Урл deploy

Опция командной строки, используемая для указания базового пути для разрешения относительных URL для активов, таких как изображения, скрипты и таблицы стилей во время компиляции. Например: ng build --deploy-url /my/assets.

Эффекты от определения deploy url и base href могут перекрываться.

  • Оба могут быть использованы для начальных скриптов, таблиц стилей, ленивых скриптов и css ресурсов.

Однако определение base href имеет несколько уникальных эффектов.

  • Определение базового href может использоваться для определения местоположения относительных активов шаблона (HTML) и относительных fetch/XMLHttpRequests.

Также base href может быть использован для определения базы Angular router'а по умолчанию (см. APP_BASE_HREF). Пользователям с более сложными настройками может понадобиться вручную настроить токен APP_BASE_HREF в приложении (например, база маршрутизации приложения — /, но assets/scripts/etc. находятся по адресу /assets/).

В отличие от base href, который может быть определен в одном месте, deploy url должен быть жестко закодирован в приложении во время сборки. Это означает, что указание deploy url снизит скорость сборки, но это печальная плата за использование опции, которая внедряется в приложение.

Вот почему base href обычно является лучшим вариантом.

Комментарии