使用base-href和deploy-url构建Angular CLI以访问CDN上的资产

时间:2017-12-19 11:00:15

标签: angular angular-cli

背景

我使用Angular CLI构建项目(包含多个应用程序)。我想在我的域上的不同子路径上发布应用,例如example.com/apps/app1/

如果我将--base-href参数设置为/apps/app1/,它可以解决有关路由器的任何问题,并且它会加载资产(js,css和图像等)。

如果我使用Location服务,我可以使用

this.location.prepareExternalUrl('/assets/data/data.json')

解决动态加载的资源(它们将解析为/apps/app1/assets/data/data.json)。

到目前为止一切顺利。但我现在希望通过CDN(例如cdn.example.com)提供应用资产,同时在原始网址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,并从CDN加载js和css文件。它还使用CDN URL解析CSS文件中的图像URL引用。

问题

从资源文件夹 动态 (在服务或模板中)加载图片或数据时,我无法找到解决问题的好方法使用deploy-url配置的网址。

如果我使用Location服务,它仍会使用base-href来解析网址,所以

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值,特别是因为这将是在同一域上托管文件以及在外部域上托管文件时可以使用的通用解决方案

问题

考虑到base-hrefdeploy-url参数,有没有办法解析资产网址?

理想情况下是官方Angular函数,如Location.prepareExternalUrl,但如果我能以某种方式从Angular获取base-href和deploy-url参数,我可以为它构建自己的服务。

我不希望在以下环境配置中定义URL:

  1. 每个应用程序需要特定的环境配置
  2. 它与构建应用程序时提供的值产生潜在冲突。

4 个答案:

答案 0 :(得分:1)

这是我解决此“ BS”问题的方法。当您的应用是例如托管在 www.domain.de/hehe

  1. angular.json中添加"deployUrl": "./",
  2. src/index.html内的<head>中添加/更新<base href="./">
  3. 在整个应用中,您将使用资产的相对路径,而不使用以下路径:<img src="./assets/img/pictureOfMyCrazyWife.png">
  4. 只需方便地运行ng buildng build --prod

通过这些简单的步骤,您便可以进行常规设置。因此无论其www.domain.de/hehewww.domain.de/hehe2www.domain.de/还是www.domain.de/lol

答案 1 :(得分:0)

要在应用程序运行时访问--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));

这个想法是获取当前执行的Javascript文件的URL,该文件是main.js(如果启用了outputHashing,则为main.hash.js),并从中删除文件名。然后在您的服务中,以--deploy-url作为构造函数参数注入@Inject(DEPLOY_URL) deployUrl: string值。

答案 2 :(得分:0)

我遇到了完全相同的情况,正如您在背景中概述的那样,同时构建base-hrefdeploy-url集的确可以使我们能够在将应用程序托管在另一台服务器上的同时,从CDN提供css和js文件。

作为在模板中动态加载资产的解决方案,我们编写了一个API,该API为此目的提供了环境变量,该变量提供了每次部署所需的适当URL。

答案 3 :(得分:-1)

这是我为几个项目所做的工作。

使用由服务器设置的动态值设置APP_BASE_HREF,例如        Cookie和SPA在初始化时读取它。 getBaseUrl函数只需读取一个        Cookie值。

{ provide: APP_BASE_HREF, useFactory: () => getBaseUrl() }

在您的CI流程中设置deployUrl。您需要动态设置BUILD和VERSION。这可以通过使用简单的shell脚本来完成。

https://my-cloud.cloudfront.net/my-app/{BUILD}/{VERSION}/