ASP.NET捆绑包如何禁用代码压缩

202

我在我的web.config(s)中都有debug="true",但是我不想让我的bundles被压缩,但是我尝试了enableoptimisations=false,但好像无法禁用它。以下是我的代码:

//Javascript
bundles.Add(new ScriptBundle("~/bundles/MainJS")
            .Include("~/Scripts/regular/lib/mvc/jquery.validate.unobtrusive.js*")
            .Include("~/Scripts/regular/lib/mvc/jquery.validate*")
            .Include("~/Scripts/regular/lib/bootstrap.js")
            .IncludeDirectory("~/Scripts/regular/modules", "*.js", true)
            .IncludeDirectory("~/Scripts/regular/pages", "*.js", true)
            .IncludeDirectory("~/Scripts/regular/misc", "*.js", true));

//CSS
bundles.Add(new StyleBundle("~/bundles/MainCSS")
            .Include("~/Content/css/regular/lib/bootstrap.css*")
            .IncludeDirectory("~/Content/css/regular/modules", "*.css", true)
            .IncludeDirectory("~/Content/css/regular/pages", "*.css", true))

2
@RickAnd-MSFT,请求是如何在禁用缩小的情况下启用捆绑。使用web.config debug = true/false或EnableOptimizations只能同时打开或关闭两者。Martin Devillers的答案允许启用捆绑而禁用缩小。 - guymid
2
对于捆绑包中的文件'x.js',请确保该文件夹中没有'x.min.js'文件,否则即使您已删除了缩小转换,捆绑包也会提供“预”缩小文件。例如,如果您有'angular.js',请删除'angular.min.js'文件;-) - stooboo
14个回答

172

条件编译指令是您的好朋友:

#if DEBUG
            var jsBundle = new Bundle("~/Scripts/js");
#else
            var jsBundle = new ScriptBundle("~/Scripts/js");
#endif

16
实际上,我认为他已经掌握了这个技巧——如果只是想关闭代码压缩,可以像Hao所说使用Bundle,否则就使用ScriptBundle实现代码打包和压缩,对吗? - Adam Tuliper
1
当您想要通过其捆绑包引用URI来加载内容,而不使用RequireJS自己的捆绑/缩小系统时,这是一个很好的解决方案。 - Norman H
1
我像Adam一样看待事物,我将ScriptBundle视为增强版的Bundle。因此,如果您想添加基本引用(没有特定的后置操作),那么Bundle对我来说是禁用特定bundle上的缩小的好方法。 - Charles HETIER
6
@RickAnd-MSFT,我认为你误解了这段代码的目的,它允许在调试模式下进行捆绑而不进行缩小,并在发布模式下进行捆绑和缩小。使用web.config中的debug = true/false或EnableOptimizations只能同时打开或关闭两者。我读了你的评论并否决了Martin的解决方案,结果发现这实际上是一种非常好的方法来实现捆绑而无需缩小。 - guymid
-1 这个“解决方案”充其量只是一个权宜之计。实际上,即使它能够工作,也会导致非常难以维护的代码。但这并不是最糟糕的事情。使用“Bundle”会导致资源被服务器以“text/html”的mime-type设置交付,而不是“text/javascript”。如果你在调试模式下应用这种方法来捆绑css文件,那么你就有点玩火了。不要这么做。请参见我的答案以获得一种更健康的方法,该方法在生产构建中确实有效。 - XDS
2
我已经测试过了,至少在Firefox中,mime类型是正确的 - 即使只使用Bundle选项。 - user230910

148
如果在web.config中有debug="true"并且在页面中使用Scripts/Styles.Render引用捆绑包,则应关闭捆绑和缩小。无论调试标志(debug true/false)如何,BundleTable.EnableOptimizations = false始终会关闭捆绑和缩小 。
您是否没有使用Scripts/Styles.Render帮助程序?如果您通过BundleTable.Bundles.ResolveBundleUrl()直接渲染对捆绑包的引用,您将始终获得缩小/捆绑的内容。

15
从这个回答中,我不确定如何只关闭代码压缩并保留代码打包 - 这可行吗? - Adam Tuliper
34
为此,最简单的方法是将脚本/样式捆绑包替换为默认没有设置转换的普通捆绑包,这将关闭缩小但仍然进行捆绑。请注意,要进行捆绑,仍需将EnableOptimizations设置为true。 - Hao Kung
2
对于捆绑包中的文件'x.js',请确保文件夹中没有'x.min.js'文件,否则尽管您已经删除了缩小转换,但捆绑将提供“预”缩小的文件。例如,如果您有'angular.js',则删除'angular.min.js' ;-) - stooboo
1
@stooboo 这就是我解决问题的方法,但你不需要删除任何东西。只需包含非压缩文件即可。 - OneHoopyFrood
2
这段代码 EnableOptimizations = false 属于哪个部分? - alex
显示剩余8条评论

92

要禁用打包和最小化,请将以下代码放入您的.aspx文件中(即使在web.configdebug=true,这也会禁用优化)

vb.net:

System.Web.Optimization.BundleTable.EnableOptimizations = false

C# .NET

System.Web.Optimization.BundleTable.EnableOptimizations = false;
如果你将 EnableOptimizations = true 设置为真,那么即使在 web.config 中设置了 debug=true,也会进行捆绑和缩小。

2
这是唯一解决我的问题的方法。我已经设置了 debug="true" 并且使用了正确的 Script.Render,但它仍然无法正常工作。还要注意的是,这不会提供任何 .min.js 文件,因此请确保包含未经缩小的依赖代码副本。 - OneHoopyFrood
2
@TCC:我认为vb.net语法中的False应该大写,我的想法有错吗? - jeremysawesome
@jeremysawesome 哦,是的,我认为那是正确的,好观点 :-) 我不经常做VB程序员,所以我甚至没有注意到... - TCC
1
第一行应该是"...即使debug=false",不是吗? - UnionP
2
vb.Net 不区分大小写,False=false,就像 .tostring() = .toString() 一样。 - manuel
如果 debug=false,则禁用缩小,如果 debug=true,则启用缩小。如果 debug=true(启用缩小),并且您放置了行 System.Web.Optimization.BundleTable.EnableOptimizations = false(即使从 web.config 启用了缩小,此行也会覆盖缩小)。 - manuel

76

您可以通过清除转换来简单地关闭捆绑中的缩小。

var scriptBundle = new ScriptBundle("~/bundles/scriptBundle");
...
scriptBundle.Transforms.Clear();

当我想将所有脚本打包到单个文件中,但在调试阶段需要可读性时,我个人发现这很有用。


1
-1 这里有龙:抄袭 JsMinifier/CssMinifier 也会抄袭设置 mime-type 为 "text/css" 或 "text/javascript" 的内部机制。这在调试/发布模式下不会引起问题,但在已发布的构建(即实时部署)的 css-bundles 上会造成严重破坏:Chrome 和 Firefox 拒绝加载所述的 css-bundles,声称它们的 mime-types 被设置为 "text/html" 而不是 "text/css"。对于 js-bundles,事情总算能够解决,但将一个 js-bundle 作为 "text/html"(<- 真的吗?)交付还是有点可疑的。请参见我的答案以获取正确的方法。 - XDS
或者使用 new Bundle( 而不是 new ScriptBundle( - mBardos

29

我尝试了很多建议,但似乎没有什么效果。我浪费了很多时间,最后发现这是我的错误:

@Scripts.Render("/bundles/foundation")

无论我尝试了什么,它总是把我的JavaScript进行了缩小和捆绑。实际上,我应该使用这个:

@Scripts.Render("~/bundles/foundation")

多余的 '~' 导致了问题。 我甚至只在一个实例中再次删除它,以确定是否真的是这样。没错...希望我可以至少节省一个人在此上浪费的时间。


哇,我在过去的三个小时里一直为这个问题疯狂地努力... - Bodokh

28

结合几个答案,这对我在ASP.NET MVC 4中有效。

        bundles.Add(new ScriptBundle("~/Scripts/Common/js")
            .Include("~/Scripts/jquery-1.8.3.js")
            .Include("~/Scripts/zizhujy.com.js")
            .Include("~/Scripts/Globalize.js")
            .Include("~/Scripts/common.js")
            .Include("~/Scripts/requireLite/requireLite.js"));

        bundles.Add(new StyleBundle("~/Content/appLayoutStyles")
            .Include("~/Content/AppLayout.css"));

        bundles.Add(new StyleBundle("~/Content/css/App/FunGrapherStyles")
            .Include("~/Content/css/Apps/FunGrapher.css")
            .Include("~/Content/css/tables.css"));

#if DEBUG
        foreach (var bundle in BundleTable.Bundles)
        {
            bundle.Transforms.Clear();
        }
#endif

22

还有一些简单的方法可以手动控制压缩(和其他功能)。使用 new CssMinify() transformer 就可以实现,就像这样:

// this is in case when BundleTable.EnableOptimizations = false;
var myBundle = new StyleBundle("~/Content/themes/base/css")
    .Include("~/Content/themes/base/jquery.ui.core.css" /* , ... and so on */);
myBundle.Transforms.Add(new CssMinify());
bundles.Add(myBundle);

// or you can remove that transformer in opposite situation
myBundle.Transforms.Clear();

当你想要仅对一些包进行压缩时,这是很方便的。比如说,你正在使用一些标准(jQuery)样式,它们占用了太多浏览器请求,但你想保留你自己的未经压缩的样式表。(JavaScript同理)。


14

我结合了其他人在这个问题中给出的一些答案,提出了另一种替代方案。

目标: 始终捆绑文件,在<compilation debug="true" ... />事件中禁用JS和CSS缩小,并始终对CSS捆绑应用自定义转换。

我的解决方案:

1) 在web.config中: <compilation debug="true" ... />

2) 在 Global.asax Application_Start() 方法中:

 protected void Application_Start() {
     ...
     BundleTable.EnableOptimizations = true; // Force bundling to occur

     // If the compilation node in web.config indicates debugging mode is enabled
     // then clear all transforms. I.e. disable Js and CSS minification.
     if (HttpContext.Current.IsDebuggingEnabled) {
         BundleTable.Bundles.ToList().ForEach(b => b.Transforms.Clear());
     }

      // Add a custom CSS bundle transformer. In my case the transformer replaces a
      // token in the CSS file with an AppConfig value representing the website URL
      // in the current environment. E.g. www.mydevwebsite in Dev and
      // www.myprodwebsite.com in Production.
      BundleTable.Bundles.ToList()
          .FindAll(x => x.GetType() == typeof(StyleBundle))
          .ForEach(b => b.Transforms.Add(new MyStyleBundleTransformer()));
     ...
}

10
如果将以下属性设置为false,则会禁用捆绑和最小化。
在Global.asax.cs文件中,按照下面的说明添加行。
protected void Application_Start()
{
    System.Web.Optimization.BundleTable.EnableOptimizations = false;
}

我就是不明白为什么当我关闭这个功能时,我的less文件会被转换成css?当我启用优化时,捆绑less文件就不再起作用了。 - FrenkyB

7
这里是如何在每个捆绑包上禁用代码压缩的方法:
bundles.Add(new StyleBundleRaw("~/Content/foobarcss").Include("/some/path/foobar.css"));
bundles.Add(new ScriptBundleRaw("~/Bundles/foobarjs").Include("/some/path/foobar.js"));

注意事项:你的捆绑路径不能与发布版本中的任何实际路径重合,否则将无法使用。此外,请确保避免在捆绑名称中使用.js、.css、.和_。将名称保持简单明了,就像上面的示例一样。
以下是辅助类。请注意,为了使这些类具有未来可扩展性,我们进行手术式地删除js/css缩小实例,而不是使用.clear(),并且我们还插入了一个mime-type-setter转换,否则,在处理css-bundle时,生产构建很容易遇到问题(火狐和Chrome拒绝mime-type设置为“text/html”的css bundle,默认值):
internal sealed class StyleBundleRaw : StyleBundle
{
        private static readonly BundleMimeType CssContentMimeType = new BundleMimeType("text/css");

        public StyleBundleRaw(string virtualPath) : this(virtualPath, cdnPath: null)
        {
        }

        public StyleBundleRaw(string virtualPath, string cdnPath) : base(virtualPath, cdnPath)
        {
                 Transforms.Add(CssContentMimeType); //0 vital
                 Transforms.Remove(Transforms.FirstOrDefault(x => x is CssMinify)); //0
        }
        //0 the guys at redmond in their infinite wisdom plugged the mimetype "text/css" right into cssminify    upon unwiring the minifier we
        //  need to somehow reenable the cssbundle to specify its mimetype otherwise it will advertise itself as html and wont load
}

internal sealed class ScriptBundleRaw : ScriptBundle
{
        private static readonly BundleMimeType JsContentMimeType = new BundleMimeType("text/javascript");

        public ScriptBundleRaw(string virtualPath) : this(virtualPath, cdnPath: null)
        {
        }

        public ScriptBundleRaw(string virtualPath, string cdnPath) : base(virtualPath, cdnPath)
        {
                 Transforms.Add(JsContentMimeType); //0 vital
                 Transforms.Remove(Transforms.FirstOrDefault(x => x is JsMinify)); //0
        }
        //0 the guys at redmond in their infinite wisdom plugged the mimetype "text/javascript" right into jsminify   upon unwiring the minifier we need
        //  to somehow reenable the jsbundle to specify its mimetype otherwise it will advertise itself as html causing it to be become unloadable by the browsers in published production builds
}

internal sealed class BundleMimeType : IBundleTransform
{
        private readonly string _mimeType;

        public BundleMimeType(string mimeType) { _mimeType = mimeType; }

        public void Process(BundleContext context, BundleResponse response)
        {
                 if (context == null)
                          throw new ArgumentNullException(nameof(context));
                 if (response == null)
                          throw new ArgumentNullException(nameof(response));

         response.ContentType = _mimeType;
        }
}

为了使整个过程正常工作,您需要安装以下内容(通过NuGet):
WebGrease 1.6.0+ Microsoft.AspNet.Web.Optimization 1.1.3+
同时,您的web.config文件应该像这样进行优化:
<runtime>
       [...]
       <dependentAssembly>
        <assemblyIdentity name="System.Web.Optimization" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-x.y.z.t" newVersion="x.y.z.t" />
       </dependentAssembly>
       <dependentAssembly>
              <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-x.y.z.t" newVersion="x.y.z.t" />
       </dependentAssembly>
        [...]
</runtime>

<!-- setting mimetypes like we do right below is absolutely vital for published builds because for some reason the -->
<!-- iis servers in production environments somehow dont know how to handle otf eot and other font related files   -->
<system.webServer>
        [...]
        <staticContent>
      <!-- in case iis already has these mime types -->
      <remove fileExtension=".otf" />
      <remove fileExtension=".eot" />
      <remove fileExtension=".ttf" />
      <remove fileExtension=".woff" />
      <remove fileExtension=".woff2" />

      <mimeMap fileExtension=".otf" mimeType="font/otf" />
      <mimeMap fileExtension=".eot" mimeType="application/vnd.ms-fontobject" />
      <mimeMap fileExtension=".ttf" mimeType="application/octet-stream" />
      <mimeMap fileExtension=".woff" mimeType="application/font-woff" />
      <mimeMap fileExtension=".woff2" mimeType="application/font-woff2" />
      </staticContent>

      <!-- also vital otherwise published builds wont work  https://dev59.com/lGct5IYBdhLWcg3wc9Eg#13597128  -->
      <modules runAllManagedModulesForAllRequests="true">
         <remove name="BundleModule" />
         <add name="BundleModule" type="System.Web.Optimization.BundleModule" />
      </modules>
      [...]
</system.webServer>

请注意,您可能需要采取额外的措施来使您的CSS捆绑在字体等方面起作用。但这是另外一个故事。

当我尝试使用此代码时,出现了“BundleMimeType不存在”的错误,它来自哪里? - pjominet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接