Угловая сборка CLI с использованием base-href и deploy-url для доступа к активам на CDN
Фон
Я использую Angular CLI для создания проекта (с несколькими приложениями). Я хочу опубликовать приложения на отдельных подпутьях в моем домене, например example.com/apps/app1/
.
Если я установил параметр --base-href
в /apps/app1/
он решает все проблемы, связанные с маршрутизатором, и он будет загружать активы (js, css и images и т.д.) Просто отлично.
Если я использую службу Location
, я могу использовать
this.location.prepareExternalUrl('/assets/data/data.json')
для разрешения динамически загружаемых активов (они будут разрешены /apps/app1/assets/data/data.json
).
Все идет нормально. Но теперь я хочу обслуживать активы приложения через CDN, например cdn.example.com
, при размещении самого приложения на исходном url example.com/apps/app1/
. Итак, теперь я создаю приложение, используя:
ng build -prod --app app1 --base-href "/apps/app1/" --deploy-url "http://cdn.example.com/app-assets/apps/app1/"
На этот раз я применяю параметры --base-href
и --deploy-url
. Он отлично работает в том, что он использует base-href, чтобы помочь маршрутизатору разрешить URL-адрес и загружает файлы js и css из CDN. Он также решает ссылки URL-адреса изображения в файлах CSS с использованием URL-адреса CDN.
Эта проблема
При загрузке изображений или данных из папки с ресурсами динамически (в службе или шаблоне) я не могу найти хороший способ для этого разрешить URL-адреса, используя конфигурацию deploy-url
.
Если я использую службу Location
, она все еще использует base-href
для разрешения URL-адресов, поэтому
this.location.prepareExternalUrl('/assets/data/data.json')
будет по-прежнему разрешать /apps/app1/assets/data/data.json
вместо http://cdn.example.com/app-assets/apps/app1/assets/data/data.json
.
Я ожидал, что он будет использовать значение deploy-url
если оно определено, тем более, что это будет общее решение, которое будет работать при размещении файлов в одном домене и при размещении файлов во внешнем домене.
Вопрос
Есть ли способ разрешить URL-адреса активов с учетом параметров base-href
и deploy-url
?
В идеале официальная функция Angular, такая как Location.prepareExternalUrl
, но если я могу каким-то образом получить параметры base-href и deploy-url из Angular, я мог бы создать для себя собственный сервис.
Я бы не хотел определять URL-адреса в конфигурации среды, поскольку:
- Это потребует определенных конфигураций среды для каждого приложения
- Это создает потенциальный конфликт со значениями, которые предоставляются при создании приложения.
Ответы
Ответ 1
Чтобы получить доступ к значению --deploy-url
во время выполнения приложения, создайте deploy-url.ts
с помощью:
export const DEPLOY_URL = new InjectionToken<string>('deployUrl');
И используйте этот фрагмент в вашем файле main.ts:
const deployUrl = (function() {
const scripts = document.getElementsByTagName('script');
const index = scripts.length - 1;
const mainScript = scripts[index];
return mainScript.src.replace(/main.*?\.js$/, '');
})();
const DEPLOY_URL_PROVIDER = {
provide: DEPLOY_URL,
useValue: deployUrl,
};
platformBrowserDynamic([DEPLOY_URL_PROVIDER])
.bootstrapModule(AppModule)
.catch(err => console.error(err));
Идея состоит в том, чтобы получить URL исполняемого в настоящий момент файла Javascript, который является main.js (или main.hash.js, если outputHashing
включен), и удалить из него имя файла. Затем в ваших сервисах введите значение --deploy-url
с @Inject(DEPLOY_URL) deployUrl: string
в качестве параметра конструктора.
Ответ 2
Я столкнулся с точно такой же ситуацией, и, как вы описали в Фон, сборка с использованием набора base-href
и deploy-url
работает в том смысле, что мы можем обслуживать наши файлы CSS и JS. из CDN при размещении приложения на другом сервере.
В качестве решения для динамически загружаемых ресурсов в наших шаблонах мы написали API, который предоставляет переменные среды для этой цели, которые предоставляют соответствующие URL-адреса, необходимые для развертывания.
Ответ 3
Вот как я сделал для нескольких проектов.
Установите APP_BASE_HREF, используя динамическое значение, установленное сервером, например Cookie, и SPA считывает его при инициализации. Функция getBaseUrl просто читает значение cookie.
{ provide: APP_BASE_HREF, useFactory: () => getBaseUrl() }
Установите deployUrl как часть вашего процесса CI. Вам нужно установить BUILD и VERSION динамически. Это можно сделать с помощью простого сценария оболочки.
https://my-cloud.cloudfront.net/my-app/{BUILD}/{VERSION}/