从多个CDN位置创建脚本包

假设我们的应用程序处于脱机状态,即我们无法使用第三方CDN,因此我们正在创建自己的应用程序。 我想在一个单独的(父)Web应用程序中托管所有供应商脚本,然后将它们包含在其他几个MVC应用程序的捆绑包中。

例如

  • http://localhost/parentWeb/Scripts/jquery.js
  • http://localhost/parentWeb/Scripts/jquery-ui.js
  • http://localhost/parentWeb/Scripts/globalize.js

我想在ASP.NET MVC App网站中包含: http://localhost/parentWeb/childWeb

即做这样的事情:

 bundles.UseCdn = true; bundles.Add( new ScriptBundle( "~/bundles/VendorScripts", "http://localhost/parentWeb/Scripts/jquery.js", "http://localhost/parentWeb/Scripts/jquery-ui.js", "http://localhost/parentWeb/Scripts/globalize.js")); 

……当然这是不可能的。 有一个很好的解决方法吗?

您无法捆绑外部资源。 如果你仔细想想,为什么你不能这样做是有道理的。 它需要捆绑器实际下载资源并在它可以使用之前将其保存到文件系统,当然如果无法访问外部资源,则可以异步进行某种回退。 然后,它必须在每个页面加载时执行此操作,因为它无法在不首先获取资源的情况下检查lastmod(因此,知道它是否确实需要重新绑定)。

如果您使用CDN资源,则捆绑程序仅将URL直接打印到页面; 它没有做任何修改。 即便如此,它只允许你创建一个只包含一个URL的“捆绑”,因为1)捆绑多个CDN资源是没有意义的,因为这会破坏CDN的目的,2)捆绑仅存在于此如果CDN资源不可用,则提供回退的方案。 否则,您只需将其硬编码到页面即可,而不必担心设置捆绑包。

我找到了一个与CDN无关的解决方案。 基本上,授予childWeb托管在parentWeb的子目录中, childWeb应用程序中的以下bundle配置从childWeb选择文件并像往常一样捆绑它们:

 bundles.Add( new ScriptBundle( "~/bundles/VendorScripts").Include( "~/../Scripts/jquery.js", "~/../Scripts/Scripts/jquery-ui.js", "~/../Scripts/globalize.js")); 

重要的是: ~/../ ,从根位置向上一级。

我知道这是一个古老的话题,但我来到这里寻找捆绑CDN资源的实际方法。 从@Chris Pratt的回答中,我明白这是不可能的。

如果您想知道,我正在根据Google的Web性能最佳实践优化现有项目,当有多个脚本标记时,它会给出低分,而当所有脚本捆绑到单个脚本引用中时,会给出较高的分数。

我需要一种方法来按顺序捆绑所有CDN脚本资源以及本地资源。 我在这个github repo上工作 ,这解决了我的问题。

使用它,您可以构建一个包含一个包列表的包,每个包含对cdn资源的引用,要保存的本地资源,以及一个布尔值,指示是否要将包缩小。

 List jsBundles = new List(); jsBundles.Add(new Bundle("https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js", @"~/jquery.min.js", Bundle.BundleType.JavaScript, false)); jsBundles.Add(new Bundle("https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.0/jquery-ui.min.js", @"~/jquery-ui.min.js", Bundle.BundleType.JavaScript, false)); jsBundles.Add(new Bundle(@"~/my-local-script.js", Bundle.BundleType.JavaScript, true)); 

要放在页面上,请使用

 @jsBundles.Load(); 

这将处理列表中的所有捆绑包,下载过去24小时内未下载的捆绑包的内容(每24小时更新一次或Web应用程序重新启动时) 。 下载的所有内容都将放在本地文件(指定的位置)中

所有内容将合并到最终结果中,最终结果将在脚本标记(或CSS的链接标记)中假脱机到页面中。

Load函数还接受最终脚本/ css内容的本地文件URL。 如果指定,将给出具有src到该本地文件的相对路径的标记。 例如

 @jsBundles.Load("~/js/all-my-scripts.js"); 

上面的语句将返回如下内容:

  

如果提供了Load函数的第二个参数,则可以将async属性添加到脚本标记。

它也适用于css cdn资源。 例如

 List cssBundles = new List(); cssBundles.Add(new Bundle("https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.0/jquery-ui.min.css", @"~/jquery.ui.css", Bundle.BundleType.CSS, false)); cssBundles.Add(new Bundle(@"~/css/my-local-style.css", Bundle.BundleType.CSS, true)); @cssBundles.Load("~/css/all-my-styles.css"); 

这是为了那些喜欢我的人的利益,来到这里寻找实际捆绑CDN资源的方法。

要将ScriptBundles与CDN资源一起使用,您需要使用重载的构造函数。 不幸的是,您需要为每个文件指定多个ScriptBundle

这是一篇很棒的博客文章解释: http : //www.hanselman.com/blog/CDNsFailButYourScriptsDontHaveToFallbackFromCDNToLocalJQuery.aspx

这是一段代码片段:

 bundles.UseCdn = true; var bundle = new ScriptBundle("~/bundles/bundleNameHere", "//cdn.host.path/to/file"); // Path to the version of the file on your server (in case the CDN fails) bundle.Include("~/../Scripts/path/to/file"); // JS expression to run, to test if CDN delivered the file or not bundle.CdnFallbackExpression = "window.ValueYouExpectToBeTruthy"; bundles.Add(bundle);