Как развернуть Angular 4+ (front-end) в CDN?

Я хотел бы развернуть мое приложение Angular (с AOT) в CDN, используя мой собственный REST-сервер.

Я бы хотел, чтобы первый запрос всегда отправлялся на мой REST-сервер (скажем, https://example.com/). Затем первый ответ попросит браузер загрузить первый модуль Angular из CDN.

Все запросы ресурсов (запросы API) будут, конечно, отправляться на мой REST-сервер (скажем, https://example.com/api/XXXX).

Теперь мой вопрос:

Как коды узнают, откуда загрузить следующий угловой модуль?

Может ли кто-нибудь объяснить механизм, стоящий за этим?

3 ответа

Решение

Краткий ответ: используйте опцию " --deploy-url " при выполнении "ng build".

Что делает "--deploy-url", так это форсирует <script> теги для использования абсолютного URL-адреса, используя указанный вами домен. Таким образом, браузер всегда будет знать, где загрузить статические файлы ресурсов (JavaScript, изображения и т. Д.)

=========================

Случай использования:

REST-сервер работает в нашем дата-центре. Он не только предоставляет API-интерфейсы REST, но и обслуживает исходный index.html (то есть запрос VERY FIRST от браузера всегда направляется на этот REST-сервер).

Все наши статические файлы Angular (это просто файлы JavaScript) развертываются в CDN (например, AWS, AZURE, GOOGLE...)

=========================

Без "--deploy-url" "ng build" выдаст index.html следующим образом:

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>MyApp</title>
  <base href="/">

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
  <app-root>Loading...</app-root>
  <script type="text/javascript" src="/inline.bundle.js"></script>
  <script type="text/javascript" src="/polyfills.bundle.js"></script>
  <script type="text/javascript" src="/styles.bundle.js"></script>
  <script type="text/javascript" src="/vendor.bundle.js"></script>
  <script type="text/javascript" src="/main.bundle.js"></script>
 </body>
</html>

С "--deploy-url", "ng build" выдаст index.html следующим образом:

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>MyApp</title>
  <base href="/">

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
  <app-root>Loading...</app-root>
  <script type="text/javascript" src="https://any.cdn.com/inline.bundle.js"></script>
  <script type="text/javascript" src="https://any.cdn.com/polyfills.bundle.js"></script>   
  <script type="text/javascript" src="https://any.cdn.com/styles.bundle.js"></script>    
  <script type="text/javascript" src="https://any.cdn.com/vendor.bundle.js"></script>  
  <script type="text/javascript" src="https://any.cdn.com/main.bundle.js">
  </script>
</body>
</html>

=========================

Как выглядит развертывание:

Например,

ng build --deploy-url YOUR-CDN-SERVER-DOMAIN --prod --aot

Это должно создать папку /dist со всем (включая index.html) в ней. Затем просто переместите index.html на свой REST-сервер и разверните оставшиеся файлы в CDN.

Теперь пользователи могут сначала зайти на ваш собственный домен www.example.com. Вы можете поместить все эти сгенерированные Angular JS-файлы в любые CDN, которые вам нужны, не беспокоясь о CORS.

=======================

Заметки:

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

Не уверен, поможет ли это, но это мое решение для размещения внешнего интерфейса на S3 с REST-сервером в нашем центре данных: у нас есть CNAME www.example.com, указывающий на корзину S3, где живет внешний интерфейс, и api.example.com на наш REST-сервер.

В вашем environment.prod.ts укажите apiUrl:

export const environment = {
    production: true,
    apiUrl: 'https://api.example.com'
};

который вы можете использовать для вызовов API следующим образом:

import {environment} from '../environments/environment';

getHttp(url: string, params?: RequestOptions): Observable<any> {
    // prefix API URL if not already given
    if (url.indexOf(environment.apiUrl) === -1) {
        url = environment.apiUrl + url;
    }
    return this.http.get(url, params).map().catch();
}

Просто убедитесь, что вы действительно передаете окружающую среду, а не только цель при сборке:

ng build --env=prod

И самое главное, разрешить запросы от www. к api. (CORS), отправив эти заголовки с вашего сервера REST:

Access-Control-Allow-Origin: https://www.example.com
Vary: Origin

Примечание: это также делает использование прокси для локальной разработки устаревшим, потому что вы можете просто указать локальный apiUrl, включая порт в вашем environment.ts

Вам нужно использовать Cdnify. Попробуйте использовать библиотеку, такую ​​как gulpCDN и т. Д.

Для нашей проблемы я загрузил все файлы Dist после сборки prod в S3 и запустил

gulp cdnify, который заменит все ссылки локального хоста основных и комплектных файлов на ссылки из корзины s3 (вам нужно указать корень непосредственно в библиотеке, чтобы gulp сделал это автоматически) в index.html

файл, который будет сервером моего узла сервера, а затем использовать его.

Причина, по которой мы остановились на этом подходе, заключается в том, что Node медленнее обслуживает статические файлы, так что используя этот механизм, мы можем добиться более высокой производительности, после загрузки index.html вам не нужно беспокоиться о других модулях, так как все файлы поставщика и основные файлы js будут загружен из ссылки cdn, которая была изменена в index.html .

Для справки я использовал эти библиотеки Gulp S3 и gulp cdinfy

Другие вопросы по тегам