【问题标题】:Bundler not including .min filesBundler 不包括 .min 文件
【发布时间】:2012-08-12 09:45:44
【问题描述】:

mvc4 bundler 有一个奇怪的问题,不包括扩展名为 .min.js 的文件

在我的 BundleConfig 类中,我声明

public static void RegisterBundles(BundleCollection bundles)
{
    bundles.Add(new ScriptBundle("~/Scripts/jquery")
        .Include("~/Scripts/jquery-1.8.0.js")
        .Include("~/Scripts/jquery.tmpl.min.js"));            
}

在我看来,我声明

<html>
    <head>
    @Scripts.Render("~/Scripts/jquery")
    </head><body>test</body>
</html>

而当它渲染时,它只渲染

<html>
    <head>
         <script src="/Scripts/jquery-1.8.0.js"></script>
    </head>
    <body>test</body>
</html>

如果我将 jquery.tmpl.min.js 重命名为 jquery.tmpl.js(并相应地更新包中的路径),两个脚本都会正确呈现。

是否有一些配置设置导致它忽略“.min.js”文件?

【问题讨论】:

  • 我正在使用 MVC 4 bundler,它包含 .min.js 文件。
  • RTM 版本还是 RC?对我来说,它在 RC 中也可以正常工作
  • 这个想法是在调试模式下工作,将使用没有缩小的“开发”版本,当您处于非调试模式时,选择缩小版本。要查看它的实际效果,请将您的 web.config 调试值从 true 更改为 false。
  • 在某些情况下,您没有脚本的非缩小版本。如果两个文件都存在,我可以可能理解它。
  • 默认情况下它的工作方式是这样的,真可惜...当然,文件可能已经缩小,但我认为微软没有看到添加 pre-将脚本缩小到捆绑包以用于缓存清除目的(漂亮的小 v 参数散列被添加到 url,并在文件内容更改时更改)

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


【解决方案1】:

我最初发布的解决方案是有问题的(是一个肮脏的黑客)。正如许多评论者所指出的那样,调整后的行为在 Microsoft.AspNet.Web.Optimization 包中发生了变化,并且调整不再起作用。现在我无法使用 1.1.3 版的软件包重现该问题。

请参阅 System.Web.Optimization.BundleCollection 的来源(例如,您可以使用 dotPeek)以更好地了解您将要做什么。 另请阅读Max Shmelev's answer

原答案

将 .min.js 重命名为 .js 或执行类似的操作

    public static void AddDefaultIgnorePatterns(IgnoreList ignoreList)
    {
        if (ignoreList == null)
            throw new ArgumentNullException("ignoreList");
        ignoreList.Ignore("*.intellisense.js");
        ignoreList.Ignore("*-vsdoc.js");
        ignoreList.Ignore("*.debug.js", OptimizationMode.WhenEnabled);
        //ignoreList.Ignore("*.min.js", OptimizationMode.WhenDisabled);
        ignoreList.Ignore("*.min.css", OptimizationMode.WhenDisabled);
    }

    public static void RegisterBundles(BundleCollection bundles)
    {
        bundles.IgnoreList.Clear();
        AddDefaultIgnorePatterns(bundles.IgnoreList);
        //NOTE: it's bundles.DirectoryFilter in Microsoft.AspNet.Web.Optimization.1.1.3 and not bundles.IgnoreList

        //...your code
     }

【讨论】:

  • 也感谢我 - 所以把它添加到我的 MVC4 陷阱列表中:)
  • 这是一个漫长的 wtf 时刻,他们本来可以添加那些被注释掉的 min 文件,结果是有理由或其他结果,现在浪费了整整一个小时想知道是谁从输出中窃取了我的脚本文件。
  • 根据 Fatal 在 OP 中的评论,如果缩小版和常规版本都存在(例如 jquery),则此解决方案最终会重新处理重复引用。
  • M$,当 somefile.min.js 被明确指定,或者只有 .min.js 文件存在时,那么只包含 .min.js 文件!否则,只需应用当前行为!
  • 令人难以置信的是,实际的类被称为“IgnoreList”,但它直接派生自 Object。没有 LINQ,没有迭代。 - msdn.microsoft.com/en-us/library/…
【解决方案2】:

微软暗示了以下行为(我更喜欢在我的项目中遵循它):

短版

  1. 您的项目中的同一文件夹下有脚本的调试版本和缩小版本:
    • script.js
    • script.min.js
  2. 您只将 script.js 添加到代码中的包中。

因此,您将自动script.js 包含在 DEBUG 模式和 script.min.js 处于 RELEASE 模式。

长版

你也可以有 .debug.js 版本。在这种情况下,该文件包含在 DEBUG 中的以下优先级中:

  1. script.debug.js
  2. script.js

在发布中:

  1. script.min.js
  2. script.js

注意

顺便说一句,在 MVC4 中拥有 .min 版本的脚本的唯一原因是无法自动处理缩小版本的情况。例如以下代码不能自动混淆:

if (DEBUG) console.log("Debug message");

在所有其他情况下,您可以只使用脚本的调试版本。

【讨论】:

  • 很好的解释,但是,OP 的问题是某些脚本 (jquery.tmpl) 没有、没有附带、没有下载文件的非最小版本。如果在调试模式下没有非最低版本,捆绑器会完全忽略脚本文件
  • 同意,很好的解释,但它根本没有回答 OP 的问题。
  • 短版不适合我。 “script.js”将包含在这两种发布类型中。我切换了 DEBUG/RELEASE 并且(当我查看源代码时)“script.js”是选择/渲染的那个。
  • user981375,还需要在web.config文件中设置
  • 我更喜欢这个答案,因为它是一种“最佳实践”方法,并解释了如何遵循捆绑程序的默认规则来实现相同的目标。
【解决方案3】:

就我而言,我使用的是(太棒了!)Knockout.js 库,它作为 Debug/Non 版本提供:

"~/Scripts/knockout-{Version}.js"
"~/Scripts/knockout-{Version}.Debug.js"

为了完成这项工作,我在我的 Bundle 中包含了“Knockout-{Version}.js”(非调试)并获得了 .debug。 js 文件处于调试模式。

【讨论】:

    【解决方案4】:

    伙计们 我会一直保留它,直到微软一起行动

    试试这个

    在 RegisterBundles 中为 Kendo 创建此捆绑包

    bundles.Add(new StyleBundle("~/Content/kendo/css").Include(
                        "~/Content/kendo/2012.3.1121/kendo.common.min.css",
                         "~/Content/kendo/2012.3.1121/kendo.dataviz.min.css",
                          "~/Content/kendo/2012.3.1121/kendo.blueopal.min.css"
     ));
    

    在 _Layout.cshtml 中放这个:

    @if (HttpContext.Current.IsDebuggingEnabled)
     { 
    <link href="@Url.Content("~/Content/kendo/2012.3.1121/kendo.common.min.css")"      
    rel="stylesheet"  type="text/css" />
    <link href="@Url.Content("~/Content/kendo/2012.3.1121/kendo.dataviz.min.css")" 
    rel="stylesheet" type="text/css" />   
    <link href="@Url.Content("~/Content/kendo/2012.3.1121/kendo.blueopal.min.css")"    
    rel="stylesheet" type="text/css" />
     }
     else
     {
         @Styles.Render("~/Content/kendo/css")   
     }
    

    通过这种方式,我们可以在生产中获得最好的捆绑包,并在调试中获得参考

    当微软修复他们的 MVC 4 代码时修复它

    【讨论】:

    • 我根本不喜欢这个提议的解决方案。您现在必须在(至少)两个地方维护这组脚本
    • 这几乎违背了捆绑的目的,你不觉得吗?
    • 捆绑已经以这种方式工作。如果您在调试模式下运行项目,每个 CSS 文件都是单独加载的,但是当您在发行版中运行时,它们会合并并缩小为一个。 if 块中的代码与在调试模式下自动呈现在页面上的代码相同。
    【解决方案5】:

    Bundler 有很多好处check this page但是

    Microsoft MVC4 平台认为您至少有每个脚本或样式包的缩小版本和未缩小版本(也可以使用其他文件,如 Debug 和 vsdoc)。所以我们在只有这些文件之一的情况下会遇到麻烦。

    您可以永久更改 web.config 文件中的调试状态以处理输出:

    <compilation debug="false" targetFramework="4.0" />
    

    查看输出变化!文件过滤已更改。为了达到目的,我们必须改变会改变应用程序逻辑的忽略大小写过滤!

    【讨论】:

    • 添加 debug="false" 仍然对我不起作用。即使我也清除了 IgnoreList,min.js 文件仍然不包括在内...
    【解决方案6】:

    如果您只有文件的缩小版本,我发现的最简单的解决方案是复制缩小文件,从复制的文件名中删除 .min,然后在捆绑包中引用非缩小文件名。

    例如,假设您购买了一个 js 组件,他们给了您一个名为 some-lib-3.2.1.min.js 的文件。要在捆绑包中使用此文件,请执行以下操作:

    1. 复制 some-lib-3.2.1.min.js 并将复制的文件重命名为 some-lib-3.2.1.js。在您的项目中包含这两个文件。

    2. 在你的包中引用非缩小文件,像这样:

      bundles.Add(new ScriptBundle("~/bundles/libraries").Include(
          "~/Scripts/some-lib-{version}.js"
      ));
      

    仅仅因为名称中没有“min”的文件实际上被缩小了,不应该引起任何问题(除了它本质上不可读的事实)。它仅在调试模式下使用,并作为单独的脚本写出。当不处于调试模式时,预编译的 min 文件应包含在您的包中。

    【讨论】:

      【解决方案7】:

      一种简单的方法是重命名 .min 文件,例如您有 abc.min.css,而不是将此文件重命名为 abc_min.css 并将其添加到您的包中。我知道这不是正确的方法,而只是一个临时解决方案。谢谢,编码愉快。

      【讨论】:

      • 每次nuget下载文件,都需要重命名。
      • 我知道这不是正确的做法,只是一个临时解决方案
      • 把这条线对我有用 // BundleTable.EnableOptimizations = true;
      【解决方案8】:

      我找到了一个至少在 MVC5 中有效的好解决方案,您可以使用 Bundle 而不是 ScriptBundle。在这种情况下,它没有我们不喜欢的ScriptBundle 的智能行为(忽略.min 等)。在我的解决方案中,我将Bundle 用于带有.min 和.map 文件的3d 派对脚本,我将ScriptBundle 用于我们的代码。我没有注意到这样做的任何缺点。要使其以这种方式工作,您需要添加原始文件,例如angular.js,它会在调试中加载 angular.js,并在发布模式下捆绑 angular.min.js。

      【讨论】:

      • 禁用优化时似乎不起作用 (ScriptTable.EnableOptimizations = false)。不呈现包含模式的脚本路径(例如~/Scripts/thirdpartylib/*.js)。它确实EnableOptimizations = true 时起作用,但ScriptBundle 也是如此。
      • 我也将它与 false 一起使用(在开发过程中),我没有你描述的问题,所以它可能是其他影响它的东西。你还需要做 IncludeDirectory 而不是包含以使模式起作用。
      • 您确定它正在渲染您文件的“.min.js”版本吗?您使用的是来自命名空间 System.Web.Optimizations 还是来自 nuget 包 Microsoft.Web.Optimizations 的捆绑包?
      • 我使用 System.Web.Optimization 并检查它是否呈现最小版本,但我发现我实际上不使用 IncludeDirectory,但如果它不适用于最小版本会很奇怪不过...由于 IncludeDirectory 对我来说还不够,我进行了自定义扫描并使用 Include 添加了所有过滤器,因此模式和 IncludeDirectory 可能无法在那里正常工作,尽管这有点奇怪。
      • 不,问题有两个:只存在.min.js 文件,*.js 模式与以.min.js 结尾的文件不匹配。
      【解决方案9】:

      要呈现*.min.js 文件,您必须禁用BundleTable.EnableOptimizations,这是适用于所有捆绑包的全局设置。

      如果您只想为特定包启用优化,您可以创建自己的 ScriptBundle 类型,在枚举包中的文件时临时启用优化。

      public class OptimizedScriptBundle : ScriptBundle
      {
          public OptimizedScriptBundle(string virtualPath)
              : base(virtualPath)
          {
          }
      
          public OptimizedScriptBundle(string virtualPath, string cdnPath)
              : base(virtualPath, cdnPath)
          {
          }
      
          public override IEnumerable<BundleFile> EnumerateFiles(BundleContext context)
          {
              if (context.EnableOptimizations)
                  return base.EnumerateFiles(context);
              try
              {
                  context.EnableOptimizations = true;
                  return base.EnumerateFiles(context);
              }
              finally
              {
                  context.EnableOptimizations = false;
              }
          }
      }
      

      对于应始终使用缩小文件的捆绑包,使用OptimizedScriptBundle 而不是ScriptBundle,无论是否存在非缩小文件。

      用于 ASP.NET MVC 的 Kendo UI 示例,它仅作为缩小文件的集合分发。

      bundles.Add(new OptimizedScriptBundle("~/bundles/kendo")
              .Include(
                  "~/Scripts/kendo/kendo.all.*",
                  "~/Scripts/kendo/kendo.aspnetmvc.*",
                  "~/Scripts/kendo/cultures/kendo.*",
                  "~/Scripts/kendo/messages/kendo.*"));
      

      【讨论】:

      • 我在生产发布操作中遇到了一些缺失的脚本,并认为这是一个 MVC 问题,我找到了这个答案。你瞧,剑道也参与其中。使用它太久了,我想尽一切办法摆脱剑道
      • @Felipe 我遇到了同样的情况,这就是我写这个答案的原因。剑道太可怕了我希望我的示例对您有所帮助。
      猜你喜欢
      • 2013-06-06
      • 2012-01-23
      • 2017-08-24
      • 1970-01-01
      • 1970-01-01
      • 2017-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多