【问题标题】:Using CDN with <img> tags使用带有 <img> 标签的 CDN
【发布时间】:2023-11-23 23:36:01
【问题描述】:

我刚刚添加了一个 CDN 服务来加快我的网站加载速度。 我对使用&lt;img&gt; 标签获取的照片有疑问。

我有很多这样的案例:

// userProfile.thumbnailPhotoSrc = some/relative/path.png    
ng-src="{{userProfile.thumbnailPhotoSrc}}"

(我使用 AngularJS)。

在启动时,我有一个将 CDN 端点保存到 window.cdn 变量的脚本。 如果脚本确定没有可用的端点:

window.cdn = '';

所以我希望能够做类似的事情:

ng-src="window.cdn + {{userProfile.thumbnailPhotoSrc}"

但这是不可能的,因为 window.cdn 没有被评估。但这都不起作用:

ng-src="{{window.cdn + userProfile.thumbnailPhotoSrc}"

因为我只能访问{{}} 下的$scope 属性。 我无法将 CDN 端点保存到 $scope,因为每个控制器都存在一个 $scope(我有很多,这是不可维护的)。

我想到的最后一件事是,希望 ng-src 允许这样做 - 添加一个在任何 ng-src 属性上运行的转换函数,但我找不到如何做到这一点。

你建议我做什么?请记住,如果 CDN 出现故障,我希望网站从 CDN 获取照片并回退到源服务器(获取相对路径)。我怎样才能获得这种行为?

谢谢

【问题讨论】:

  • 嗨,johni,您是如何从 CDN 获取图像的?您最终是否希望访问 API 的端点来检索图像数据?此外,只是一个小提示 - 您不需要引号内的“{{}}”。有时这会把事情搞砸。
  • 我使用与 userProfile.thumbnailPhotoSrc 相同的相对路径,只是在不同的域中。例如:'https://blabla.cdn.com/' + {{userProfile.thumbnailPhotoSrc}} - 将被评估为 CDN 的正确地址。
  • 我认为这可能会有所帮助:*.com/questions/11938380/…
  • 在您的示例代码中,您编写 window.CDNwindow.cdn。这是偶然还是与您的问题有关?
  • 误了:),已编辑。

标签: javascript angularjs cdn content-delivery-network


【解决方案1】:

你可以在 Angular 中创建一个custom filter

然后你会在你的模板中:

ng-src="{{userProfile.thumbnailPhotoSrc | cdn}"

您可以将 $window 服务作为依赖项添加到过滤器服务中,这样您就不必从全局对象中拉取它,您也可以测试过滤器。

【讨论】:

  • 这很好,我不知道这一点,但如果我有 1000 个 标签怎么办?我需要回顾所有这些。我正在寻找一种方法来避免这种情况。
  • @johni — 如果您不想将它们推过过滤器,那么处理 1000 个 img 标签的方式肯定是一样的?
【解决方案2】:

如果您尝试更新所有&lt;img&gt; 标签的src。你可以创建一个指令:

angular.module('imageCdnSrc', [])
.directive('img',['$interpolate', function($interpolate) {
    return {
    restrict: 'E',
    scope: false,
    compile: function(element, attrs) {
      var ngSrc = attrs.ngSrc;
      delete attrs.ngSrc; // prevent ngSrc directive to trigger

      return function($scope,element,attrs) {
        var ngSrcVal = $interpolate(ngSrc)($scope); //returns the string value of ngSrc

        /* Add Logic Below to decide what to do */
        if(window.cdn && ngSrcVal && ngSrcVal.length>0){
          attrs.ngSrc = window.cdn + ngSrcVal;
          /* if image fails to load with cdn, load the default */
          element.one('error', function() {
            angular.element(this).attr("src", ngSrcVal);
          });
        }
        else{
          attrs.ngSrc = ngSrcVal;
        }
      };      
    }
  };
}]);

【讨论】:

  • 是什么让它在 $observe 的 ngSrc 指令回调之前执行?
  • @johni 好的,我更新了,所以在它编译之前它会将 window.cdn 附加到 ngSrc
  • 如果ng-src="{{userProfile.thumbnailPhotoSrc}}" 在评估{{}} 之前调用指令的编译函数。
  • @johni 是的,它就是这样工作的。 img 'src' 在两者之后才会渲染。这是一个在 plunker 上工作的例子。 plnkr.co/edit/PGNWoF1w1OdmEFUSglKw?p=info
  • @johni 我刚刚更新了代码以在评估之前和之后进行演示。