C# MVC4 捆绑 CSS 失败 意外令牌,找到“@import”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11970293/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 19:54:18  来源:igfitidea点击:

MVC4 bundling CSS failed Unexpected token, found '@import'

c#asp.net-mvcbundleasp.net-optimization

提问by Kyle

I'm trying to use bundling to combine & minify some CSS files. In my Global.aspx.cs Application_StartI have the following:

我正在尝试使用捆绑来组合和缩小一些 CSS 文件。在我的 Global.aspx.cs 中,Application_Start我有以下内容:

    var jsBundle = new Bundle("~/JSBundle", new JsMinify());
    jsBundle.AddDirectory("~/Scripts/", "*.js", false);
    jsBundle.AddFile("~/Scripts/KendoUI/jquery.min.js");
    jsBundle.AddFile("~/Scripts/KendoUI/kendo.web.min.js");
    BundleTable.Bundles.Add(jsBundle);

    var cssBundle = new Bundle("~/CSSBundle", new CssMinify());
    cssBundle.AddDirectory("~/Content/", "*.css", false);
    cssBundle.AddDirectory("~/Content/themes/base/", "*.css", false);
    cssBundle.AddFile("~/Styles/KendoUI/kendo.common.min.css");
    cssBundle.AddFile("~/Styles/KendoUI/kendo.default.min.css");
    BundleTable.Bundles.Add(cssBundle);

And in my .cshtml file I have the following:

在我的 .cshtml 文件中,我有以下内容:

<link href="/CSSBundle" rel="stylesheet" type="text/css" />
<script src="/JSBundle" type="text/javascript"></script>

However, when I view the source of my bundles CSS file, it has the following:

但是,当我查看 bundles CSS 文件的源代码时,它具有以下内容:

/* Minification failed. Returning unminified contents.
(40,1): run-time error CSS1019: Unexpected token, found '@import'
(40,9): run-time error CSS1019: Unexpected token, found '"jquery.ui.base.css"'

.... lots more

.... 更多

Any ideas on how to resolve this?

关于如何解决这个问题的任何想法?

I did narrow it down to the following line:

我确实将其缩小到以下行:

cssBundle.AddDirectory("~/Content/themes/base/", "*.css", false);

If I only have that line of code I get the same errors.

如果我只有那行代码,我会得到同样的错误。

采纳答案by Hao Kung

There are a few issues here:

这里有几个问题:

  1. The css issue is due to including the jquery.ui.all.css, as the default minifier doesn't support following imports, and this is not what you want to do anyways as it would double include all of the jquery ui css files. So what you want to do instead is not use *.css, and instead explicitly list what jquery ui files you want to include:

     bundles.Add(new StyleBundle("~/Content/themes/base/css").Include(
            "~/Content/themes/base/jquery.ui.core.css",
            "~/Content/themes/base/jquery.ui.resizable.css",
            "~/Content/themes/base/jquery.ui.selectable.css",
            "~/Content/themes/base/jquery.ui.accordion.css",
            "~/Content/themes/base/jquery.ui.autocomplete.css",
            "~/Content/themes/base/jquery.ui.button.css",
            "~/Content/themes/base/jquery.ui.dialog.css",
            "~/Content/themes/base/jquery.ui.slider.css",
            "~/Content/themes/base/jquery.ui.tabs.css",
            "~/Content/themes/base/jquery.ui.datepicker.css",
            "~/Content/themes/base/jquery.ui.progressbar.css",
            "~/Content/themes/base/jquery.ui.theme.css"));
    
  2. Secondly you want to be using the Script/Styles.Render methods rather than explicitly referencing the bundles url as you are doing, as the helpers will automatically not bundle/minify and render individual references to each script/style asset when in debug mode, and also append a fingerprint for the bundle contents into the url so browser caching will work propertly.

    @Scripts.Render("~/JSBundle") and @Styles.Render("~/CSSBundle")
    
  3. You can also use StyleBundle/ScriptBundle which is just syntaxtic sugar for not having to pass in new Css/JsMinify.

  1. css 问题是由于包含 jquery.ui.all.css,因为默认的 minifier 不支持以下导入,无论如何这不是您想要做的,因为它会双重包含所有 jquery ui css 文件。所以你想要做的不是使用 *.css,而是明确列出你想要包含的 jquery ui 文件:

     bundles.Add(new StyleBundle("~/Content/themes/base/css").Include(
            "~/Content/themes/base/jquery.ui.core.css",
            "~/Content/themes/base/jquery.ui.resizable.css",
            "~/Content/themes/base/jquery.ui.selectable.css",
            "~/Content/themes/base/jquery.ui.accordion.css",
            "~/Content/themes/base/jquery.ui.autocomplete.css",
            "~/Content/themes/base/jquery.ui.button.css",
            "~/Content/themes/base/jquery.ui.dialog.css",
            "~/Content/themes/base/jquery.ui.slider.css",
            "~/Content/themes/base/jquery.ui.tabs.css",
            "~/Content/themes/base/jquery.ui.datepicker.css",
            "~/Content/themes/base/jquery.ui.progressbar.css",
            "~/Content/themes/base/jquery.ui.theme.css"));
    
  2. 其次,您希望使用 Script/Styles.Render 方法,而不是像您这样做时显式引用 bundles url,因为在调试模式下,帮助程序不会自动捆绑/缩小并呈现对每个脚本/样式资产的单独引用,并且还将捆绑内容的指纹附加到 url 中,以便浏览器缓存正常工作。

    @Scripts.Render("~/JSBundle") and @Styles.Render("~/CSSBundle")
    
  3. 您还可以使用 StyleBundle/ScriptBundle,它只是语法糖,无需传入新的 Css/JsMinify。

You can also check out this tutorial for more info: Bundling Tutorial

您还可以查看本教程以获取更多信息: Bundling Tutorial

回答by Andrey Borisko

Or what you can do is to write your own BundleTransform for CssMinify if of course you need such a flexibility. So, for example your code in BundleConfig.cs looks like:

或者你可以做的是为 CssMinify 编写你自己的 BundleTransform,如果你当然需要这样的灵活性。因此,例如您在 BundleConfig.cs 中的代码如下所示:

using System;
using System.Web.Optimization;
using StyleBundle = MyNamespace.CustomStyleBundle;

public class BundleConfig
{
    public static void RegisterBundles(BundleCollection bundles)
    {
        bundles.Add(new StyleBundle("~/Content/themes/base/css")
            .IncludeDirectory("~/Content/themes/base", "*.css"));
    }
}

Then what you need to add is:

那么你需要补充的是:

public class CustomStyleBundle : Bundle
{
    public CustomStyleBundle(string virtualPath, IBundleTransform bundleTransform = null)
        : base(virtualPath, new IBundleTransform[1]
            {
                bundleTransform ?? new CustomCssMinify()
            })
    {
    }

    public CustomStyleBundle(string virtualPath, string cdnPath, IBundleTransform bundleTransform = null)
        : base(virtualPath, cdnPath, new IBundleTransform[1]
            {
                bundleTransform ?? new CustomCssMinify()
            })
    {
    }
}

public class CustomCssMinify : IBundleTransform
{
    private const string CssContentType = "text/css";

    static CustomCssMinify()
    {
    }

    public virtual void Process(BundleContext context, BundleResponse response)
    {
        if (context == null)
            throw new ArgumentNullException("context");
        if (response == null)
            throw new ArgumentNullException("response");
        if (!context.EnableInstrumentation)
        {
            var minifier = new Minifier();
            FixCustomCssErrors(response);
            string str = minifier.MinifyStyleSheet(response.Content, new CssSettings()
            {
                CommentMode = CssComment.None
            });
            if (minifier.ErrorList.Count > 0)
                GenerateErrorResponse(response, minifier.ErrorList);
            else
                response.Content = str;
        }
        response.ContentType = CssContentType;
    }

    /// <summary>
    /// Add some extra fixes here
    /// </summary>
    /// <param name="response">BundleResponse</param>
    private void FixCustomCssErrors(BundleResponse response)
    {
        response.Content = Regex.Replace(response.Content, @"@import[\s]+([^\r\n]*)[\;]", String.Empty, RegexOptions.IgnoreCase | RegexOptions.Multiline);
    }

    private static void GenerateErrorResponse(BundleResponse bundle, IEnumerable<object> errors)
    {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.Append("/* ");
        stringBuilder.Append("CSS Minify Error").Append("\r\n");
        foreach (object obj in errors)
            stringBuilder.Append(obj.ToString()).Append("\r\n");
        stringBuilder.Append(" */\r\n");
        stringBuilder.Append(bundle.Content);
        bundle.Content = stringBuilder.ToString();
    }
}

And if you need some more fixes/errors you can extend this logic in FixCustomCssErrors method.

如果您需要更多修复/错误,您可以在 FixCustomCssErrors 方法中扩展此逻辑。