【问题标题】:Create a Script bundle from multiple locations从多个位置创建脚本包
【发布时间】:2013-11-27 17:02:32
【问题描述】:

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

例如

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

我想包含在 ASP.NET MVC 应用程序网站中: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"));

...这当然是目前不可能的。有没有好的解决方法?

【问题讨论】:

    标签: c# asp.net asp.net-mvc asp.net-mvc-4 bundling-and-minification


    【解决方案1】:

    您不能捆绑外部资源。如果你仔细想想,为什么你不能这样做是有道理的。它需要捆绑器实际下载资源并将其保存到文件系统,然后才能使用它,当然,如果无法访问外部资源,它会以某种回退方式异步完成。然后,它必须在每次页面加载时都这样做,因为如果不先获取资源,它就无法检查 lastmod(因此,知道它是否真的需要重新捆绑)。

    如果您使用 CDN 资源,捆绑器只会将 URL 直接打印到页面;它不做任何修改。即使那样,它也只能让您创建一个仅包含一个 URL 的“捆绑包”,因为 1) 捆绑多个 CDN 资源没有意义,因为这会破坏 CDN 的目的,以及 2) 捆绑包只存在于这个在 CDN 资源不可用时提供回退的方案。否则,只需将其硬编码到页面上,您就可以得到同样的服务,而根本不用担心设置捆绑包。

    【讨论】:

    • 虽然您不能捆绑外部资源(您的观点非常正确),但 ScriptBundle 实际上支持 CDN。这篇博文很好地解释了一切hanselman.com/blog/…
    • @BryanRayner:不确定是什么冲突。我从未说过捆绑不支持 CDN。恰恰相反,实际上,正如我提到的将 CDN 与脚本包一起使用。但是,就像我在上面的回答中所说的那样,捆绑程序实际上并没有对 CDN 资源任何事情。它只是将页面上的静态脚本标签放到 CDN 文件中。它不会将其与其他脚本或 CSS 文件缩小/合并。
    • 重新阅读您的问题,我必须同意 - 您从未说过捆绑不支持 CDN。当我最初阅读您的答案时,“您不能捆绑外部资源”似乎表明 ScriptBundles 不能用于为客户端提供外部资源。
    【解决方案2】:

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

    如果您想知道,我正在根据Google's Web Performance Best Practises 优化现有项目,当有多个脚本标签时得分较低,而当所有脚本捆绑到单个脚本引用时得分较高。

    我需要一种方法来按顺序捆绑所有 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));
    

    要放置在页面上,请使用

    @jsBundles.Load();
    

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

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

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

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

    上面的语句会返回类似:

    <script src="~/js/all-my-scripts.js"></script>
    

    如果提供了 Load 函数的第二个参数,则可以在脚本标签中添加异步属性。

    它也适用于 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");
    

    这是为了那些像我一样来到这里寻找一种实际捆绑 CDN 资源的方法的人。

    【讨论】:

    • 聪明的解决方案,但这不会破坏使用 CDN 的目的吗? Web 客户端必须从您的服务器下载完整的捆绑 CDN 脚本,因为它们不会将其保存在缓存中。使用真正的 CDN 脚本链接,关键是您的 Web 客户端很可能已经缓存了脚本文件,因为许多其他站点都链接到同一个 CDN URL。
    【解决方案3】:

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

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

    重要的一点是:~/../,它会将您从根位置提升一级。

    【讨论】:

    • 所以对于你的解决方案,在该代码中存储 cdn 路径的位置我有同样的问题,我还需要使用 cdn 在捆绑包中加载多个 css,所以请你告诉我该怎么做?
    • 你是 OP,所以我想你有权写下你想要的回应,但标题是关于多个 CDN 位置的,这不是该问题的解决方案
    • 嘿@HostMyBus,你是对的。我不接受我的回答以避免任何混淆。
    【解决方案4】:

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

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

    这是一个代码 sn-p:

    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);
    

    【讨论】:

      【解决方案5】:

      捆绑的目的是减少托管 Web 应用程序的 Web 服务器的流量。使用 bundle 脚本文件不会并行加载。当您使用本地文件时,这是必需的。

      但如果是cdn,文件将从cdn 服务器加载,因此您无需为cdn 制作捆绑包。你只需要打包本地文件

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-03-12
        • 1970-01-01
        • 1970-01-01
        • 2012-12-29
        • 2020-12-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多