从多个CDN位置创建脚本包

Гро*_*ный 11 c# asp.net asp.net-mvc asp.net-mvc-4 bundling-and-minification

我们假设我们的应用程序处于脱机状态,即我们无法使用第三方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"));
Run Code Online (Sandbox Code Playgroud)

...当然目前不可能.有一个很好的解决方法吗?

Chr*_*att 14

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

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

  • 虽然您无法捆绑外部资源(您的观点非常正确),但 ScriptBundle 实际上支持 CDN。这篇博文很好地解释了一切http://www.hanselman.com/blog/CDNsFailButYourScriptsDontHaveToFallbackFromCDNToLocalJQuery.aspx (2认同)

小智 7

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

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

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

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

List<Bundle> jsBundles = new List<Bundle>();
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));
Run Code Online (Sandbox Code Playgroud)

要放在页面上,请使用

@jsBundles.Load();
Run Code Online (Sandbox Code Playgroud)

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

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

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

@jsBundles.Load("~/js/all-my-scripts.js");
Run Code Online (Sandbox Code Playgroud)

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

<script src="~/js/all-my-scripts.js"></script>
Run Code Online (Sandbox Code Playgroud)

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

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

List<Bundle> cssBundles = new List<Bundle>();
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");
Run Code Online (Sandbox Code Playgroud)

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


Гро*_*ный 5

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

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

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