Как развернуть 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