gruntjssource-mapsgruntfilegrunt-contrib-cssminclean-css

Grunt cssmin / CleanCSS source map rebasing


I'm using cssmin with the following "Content" folder structure:

src
|--dir1
|   |--style1.css
|   |--images
|      |--image1.png
|--dir2
   |--style2.css
   |--images
      |--image2.png
dist
|--styles.min.css
|--styles.min.css.map

Where styles.min.css and styles.min.css.map are the result of concatenating/minifying all stylesheets in the"src" folder.

I first had issues where styles.min.css contained URLs for images in the wrong places (i.e. "images/image1.png" instead of "../src/dir1/images/image1.png") but thankfully this grunt configuration fixed that:

cssmin: {
        options: {
            rebase: true,
            sourceMap: true
        },
        all: {
            options: {
                keepSpecialComments: 0
            },
            files: {
                'content/dist/styles.min.css': ["content/src/dir1/style1.css", "content/src/dir2/style2.css"]
            }
        }
    }

The new problem: The generated sourcemap ("styles.min.css.map") contains sources like this: ["content/src/dir1/style1.css", "content/src/dir2/style2.css"] instead of ["../src/dir1/style1.css", "../src/dir2/style2.css"]. This means the map is pointing to the incorrect locations, such as:

"content/dist/content/src/dir1/style1.css" and "content/dist/content/src/dir2/style2.css"

What can I do to resolve this?

For reference, I have also tried the csswring, however despite sourcemaps working fine, I found general image/import url rebasing wasn't working properly, so went back to cssmin.

Thanks very much!


Solution

  • Came up with my own solution. I wrote a task which reads the source map JSON, gets the array of sources, rebases them, then writes the file again. This solution seems to work well for me, hopefully this can help someone else too if they're in a similar situation. Just run your cssmin task and then this one:

    grunt.registerTask("rebase-css-sourcemap-sources", "Rebases the CSS source map urls", function() {
    
                var filePath = "./content/dist/styles.min.css.map";
                if (grunt.file.exists(filePath)) {
                    var sourceMap = grunt.file.readJSON(filePath);
    
                    var sources = sourceMap.sources;
                    if (sources) {
                        for (var i = 0; i < sources.length; i++) {
                            sources[i] = sources[i].replace("content/src", "../src");
                        }
                        grunt.file.write(filePath, JSON.stringify(sourceMap));
                        grunt.log.ok("Rebased CSS source map source urls.");
                    }
                } else {
                    grunt.log.error("Source map file does not exist: " + filePath);
                }
            });
    

    While this solution works for me, if anyone knows of an alternative method of solving this problem which ideally just uses cssmin, that would be better.