【问题标题】:MVC4 bundling CSS failed Unexpected token, found '@import'MVC4 捆绑 CSS 失败意外令牌,找到“@import”
【发布时间】:2012-08-11 19:21:42
【问题描述】:

我正在尝试使用捆绑来合并和缩小一些 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);

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

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

但是,当我查看我的 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"'

....更多

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

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

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

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

【问题讨论】:

    标签: c# asp.net-mvc bundle asp.net-optimization


    【解决方案1】:

    这里有几个问题:

    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 方法,而不是像您正在做的那样显式引用捆绑 url,因为在调试时,帮助程序不会自动捆绑/缩小和呈现对每个脚本/样式资产的单独引用模式,并将捆绑内容的指纹附加到 url 中,以便浏览器缓存正常工作。

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

    您也可以查看本教程了解更多信息:Bundling Tutorial

    【讨论】:

    • 你错过了“~/Content/themes/base/jquery.ui.menu.css”和“~/Content/themes/base/jquery.ui.spinner.css”。
    • 好吧,它遇到@-webkit-keyframes之类的东西时也无法捆绑,所以它不仅仅是@import失败。
    • 我使用 ScriptBundle 来捆绑 CSS abd 得到了this 错误,确保使用ScriptBundle 来处理脚本,StyleBundle 来处理 CSS
    【解决方案2】:

    或者,如果您当然需要这种灵活性,您可以为 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"));
        }
    }
    

    那么你需要添加的是:

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

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

    【讨论】:

    • 此解决方案有效地从文件中删除所有@import,对吗?这可能不会使页面呈现得很好。
    • 它也没有解决它不仅在@import 上失败,而且在@-webkit-keyframes 和其他它无法识别的完全有效的CSS 上失败的事实。无用。同时,Flash 在十年前解决了这个问题,提供了一个 SWF 文件,甚至被压缩了。我试图在 HTML 中创建一个垂直包装的列(另一个“圣杯”,因为做这么简单的事情太难了),只是得知虽然“列计数”CSS 是在 2001 年定义的,但它仍然是 2015 年在 Chrome 中只实现了一半。 Flexbox 也很烂,需要预定义的高度才能工作。
    • 您使用哪个 Bundler 版本?我有 Microsoft ASP.NET Web Optimization 1.1.3 的 VS 2015。 @-webkit-keyframes 没有任何错误,我在 bundle 的输出中看到了它。
    猜你喜欢
    • 1970-01-01
    • 2013-04-14
    • 2016-09-16
    • 2019-02-06
    • 1970-01-01
    • 2012-05-17
    • 2021-02-23
    • 2013-10-22
    • 2018-05-12
    相关资源
    最近更新 更多