Search code examples
asp.net-mvcbundling-and-minification

How to avoid CSS and bundling hell?


I have the same problem for every asp.net MVC site I develop, so I am wondering if there is a solution to this.

The site works perfectly when I am developing, however, when I publish the site, I have always problems with bundling. To solve it, I have to disable optimizations.

First of all, bundling joins all the bundled CSS's in only one file in the ~\Content folder, even when all CSS's inside one bundle is inside a subdirectory. The consequence is that images referenced from the CSS's got lost because they have relative URL's.

The second problem is that for some strange reason, JS bundling system does not want all JS's inside the same file, because JS files reported errors when bundled and site does not work at all.

This is my BundleConfig.cs file that works. If I remove BundleTable.EnableOptimizations = false; at the end, nothing works. A lot of Javascript errors occur.

    public static void RegisterBundles(BundleCollection bundles)
    {
        if (bundles != null)
        {
            bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                        "~/Scripts/jquery-{version}.js"));

            bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
                        "~/Scripts/jquery.validate*"));

            // Use the development version of Modernizr to develop with and learn from. Then, when you're
            // ready for production, use the build tool at http://modernizr.com to pick only the tests you need.
            bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
                        "~/Scripts/modernizr-*"));

            bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
                      "~/Scripts/umd/popper.js",
                      "~/Scripts/bootstrap.js"));

            bundles.Add(new ScriptBundle("~/bundles/custom").Include(
                        "~/Scripts/custom.js"));

            bundles.Add(new StyleBundle("~/Content/css").Include(
                    "~/Content/site.css",
                    "~/Content/site/style.css"));

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

            bundles.Add(new ScriptBundle("~/bundles/waitMe").Include(
                    "~/Scripts/waitMe.js"));

            bundles.Add(new StyleBundle("~/Content/sweetalert").Include(
                   "~/Content/sweetalert2.min.css"));

            bundles.Add(new ScriptBundle("~/bundles/sweetalert").Include(
                    "~/Scripts/sweetalert2/sweetalert2.all.min.js"));

            bundles.Add(new ScriptBundle("~/bundles/bundle").Include(
                      "~/Scripts/bundle.js"));

            bundles.Add(new ScriptBundle("~/bundles/moment").Include(
                      "~/Scripts/moment-with-locales.js"));

            bundles.Add(new ScriptBundle("~/bundles/mask").Include(
                "~/Scripts/jquery.inputmask.js"));

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

            bundles.Add(new ScriptBundle("~/bundles/daterangepicker").Include(
                    "~/Scripts/daterangepicker.js"));

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

            bundles.Add(new ScriptBundle("~/bundles/select2").Include(
                    "~/Scripts/select2.js",
                    "~/Scripts/i18n/es.js"));

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

            bundles.Add(new ScriptBundle("~/bundles/tapatar").Include(
                    "~/Scripts/tapatar.js"));

            bundles.Add(new ScriptBundle("~/bundles/assets").Include(
                    "~/Scripts/canvas.js",
                    "~/Scripts/collapse.js",
                    "~/Scripts/settings.js",
                    "~/Scripts/template.js",
                    "~/Scripts/default-assets/active.js"));

            bundles.Add(new StyleBundle("~/Content/grid").Include(
                      "~/Scripts/DataTables/DataTables-1.10.20/css/dataTables.bootstrap4.css",
                      "~/Scripts/DataTables/FixedColumns-3.3.0/css/fixedColumns.bootstrap4.css",
                      "~/Scripts/DataTables/Responsive-2.2.3/css/responsive.bootstrap4.css",
                      "~/Scripts/DataTables/Scroller-2.0.1/css/scroller.bootstrap4.css",
                      "~/Scripts/DataTables/Select-1.3.1/css/select.bootstrap4.css",
                      "~/Scripts/DataTables/RowGroup-1.1.1/css/rowGroup.bootstrap4.css"));

            bundles.Add(new ScriptBundle("~/bundles/grid").Include(
                      "~/Scripts/DataTables/DataTables-1.10.20/js/jquery.dataTables.js",
                      "~/Scripts/DataTables/DataTables-1.10.20/js/dataTables.bootstrap4.js",
                      "~/Scripts/DataTables/FixedColumns-3.3.0/js/dataTables.fixedColumns.js",
                      "~/Scripts/DataTables/Responsive-2.2.3/js/dataTables.responsive.js",
                      "~/Scripts/DataTables/Scroller-2.0.1/js/dataTables.scroller.js",
                      "~/Scripts/DataTables/Select-1.3.1/js/dataTables.select.js",
                      "~/Scripts/DataTables/RowGroup-1.1.1/js/dataTables.rowGroup.js",
                      "~/Scripts/DataTables/dataTables.datetime.js"));

            bundles.Add(new ScriptBundle("~/bundles/editor").Include(
                    "~/Scripts/tinymce/tinymce.js"));

            bundles.Add(new StyleBundle("~/Content/imageuploader").Include(
                    "~/Content/ssi-uploader.css"));

            bundles.Add(new ScriptBundle("~/bundles/imageuploader").Include(
                    "~/Scripts/ssi-uploader.js"));

            bundles.Add(new StyleBundle("~/Content/popup").Include(
                    "~/Content/magnific-popup.css"));

            bundles.Add(new ScriptBundle("~/bundles/popup").Include(
                    "~/Scripts/jquery.magnific-popup.js",
                    "~/Scripts/i18n/jquery.magnific-popup.es.js"));

            bundles.Add(new ScriptBundle("~/bundles/fileinput").Include(
                    "~/Scripts/fileinput.js",
                    "~/Scripts/locales/es.js",
                    "~/Content/bootstrap-fileinput/themes/fas/theme.js"
                    ));

            bundles.Add(new StyleBundle("~/Content/fileinput").Include(
                    "~/Content/bootstrap-fileinput/css/fileinput.css"));

            bundles.Add(new StyleBundle("~/Content/toastr").Include(
                    "~/Content/toastr.min.css"));

            bundles.Add(new ScriptBundle("~/bundles/toastr").Include(
                    "~/Scripts/toastr.js"));

            bundles.Add(new ScriptBundle("~/bundles/cleave").Include(
                    "~/Scripts/cleave.js"));

            bundles.Add(new StyleBundle("~/Content/summernote").Include(
                    "~/Content/summernote/summernote-bs4.css"));

            bundles.Add(new ScriptBundle("~/bundles/summernote").Include(
                    "~/Scripts/summernote/summernote-bs4.js",
                    "~/Scripts/summernote/lang/summernote-es-ES.js"
                    ));

            bundles.Add(new ScriptBundle("~/bundles/apexcharts").Include(
                    "~/Scripts/apexcharts/apexcharts.js"));

            bundles.Add(new ScriptBundle("~/bundles/pace").Include(
                    "~/Scripts/inicio/pace.min.js"));

            bundles.Add(new ScriptBundle("~/bundles/home").Include(
                    "~/Scripts/inicio/jquery-2.1.3.min.js",
                    "~/Scripts/inicio/plugins.js",
                    "~/Scripts/inicio/main.js"));

            bundles.Add(new StyleBundle("~/Content/home").Include(
                    "~/Content/inicio/base.css",
                    "~/Content/inicio/vendor.css",
                    "~/Content/inicio/main.css"));

            bundles.Add(new ScriptBundle("~/bundles/paises").Include(
                    "~/Scripts/paises/cl/jquery.rut.js"));

            bundles.Add(new StyleBundle("~/Content/datepicker").Include(
                    "~/Content/bootstrap-datepicker.css"));

            bundles.Add(new ScriptBundle("~/bundles/datepicker").Include(
                    "~/Scripts/bootstrap-datepicker.js",
                    "~/Scripts/bootstrap-datepicker.es.js"
                    ));

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

            bundles.Add(new ScriptBundle("~/bundles/timepicki").Include(
                    "~/Scripts/timepicki.js"
                    ));

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

            bundles.Add(new ScriptBundle("~/bundles/fileinput").Include(
                            "~/Scripts/fileinput/fileinput.js",
                            "~/Scripts/fileinput/locales/es.js",
                            "~/Scripts/fileinput/themes/fa/theme.js"));

            bundles.Add(new ScriptBundle("~/bundles/clock").Include(
                            "~/Scripts/jclock.js"));

            bundles.Add(new ScriptBundle("~/bundles/tinymce").Include(
                            "~/Scripts/tinymce/tinymce.js",
                            "~/Scripts/tinymce/langs/es_MX.js"));

            BundleTable.EnableOptimizations = false;
        }

Is there a good practice to avoid all this hell?

Jaime


Solution

  • You have to use CssRewriteUrlTransform at the time of bundling so that relative image paths (relative from css file location) are converted to absolute path from the website root. An example is below:

    bundles.Add(new StyleBundle("~/Content/fileinput").Include("~/Content/fileinput/css/fileinput.css", new CssRewriteUrlTransform()));