I am using grunt with cssmin
to minify and concatenate css files.
Css files are well concatenated and minified but when I try to watch the non minified files in chrome dev tools under 'Sources
' tab, files appears empty.
Here is my cssmin
task:
cssmin: {
options: {
report: 'gzip',
keepSpecialComments: 0,
sourceMap: true,
outputSourceFiles: true
},
target: {
files: {
'web/assets/dist/css/vendors.min.css': [
'bower_components/bootstrap/dist/css/bootstrap.min.css',
'bower_components/chosen/chosen.min.css',
'bower_components/slabText/css/slabtext.css',
'bower_components/video.js/dist/video-js.css',
'bower_components/video.js/dist/video-js.css'
],
'web/assets/dist/css/app.min.css': [
'app/Resources/assets/css/jumbotron-narrow.css',
'app/Resources/assets/css/custom.css',
],
}
}
},
Source map setting is enabled under chrome.
web/assets/dist/css/app.min.css.map
looks like this:
{
"version":3,
"sources":["app/Resources/assets/css/jumbotron-narrow.css","app/Resources/assets/css/custom.css"],
"names":[],
"mappings":"AAeA,QAdA,KAeI,eAAgB,KADpB,QA6BA,WAEI,cAAe,IAAI,MAAM,QA7C7B,KACI,YAAa,KCUb,YAAa,eAAkB,WDHnC,QAFA,QACA,WAEI,cAAe,KACf,aAAc,KASlB,WACI,WAAY,EACZ,cAAe,EACf,YAAa,KAIjB,QACI,YAAa,KACb,MAAO,KACP,WAAY,IAAI,MAAM,QAI1B,yBACI,WACI,UAAW,OAGnB,qBACI,OAAQ,KAAK,EAIjB,WACI,WAAY,OAGhB,gBACI,QAAS,KAAK,KACd,UAAW,KAIf,WACI,OAAQ,KAAK,EAEjB,gBACI,WAAY,KAIhB,oCAII,QAFA,QACA,WAEI,cAAe,EACf,aAAc,EAGlB,QACI,cAAe,KAGnB,WACI,cAAe,GC3EvB,WACI,YAAa,eACb,IAAK,iCAAkC,mBAG3C,WACI,YAAa,YACb,IAAK,8BAA+B,mBAOxC,GACI,WAAY,KACZ,eAAgB,UAChB,YAAa,EACb,YAAa,YAAe,WAC5B,YAAa,EAAI,EAAI,IAAI,KAG7B,4BACI,QAAS,MACT,YAAa,KACb,aAAc,KACd,cAAe,IAGnB,UACI,UAAW,MACX,WAAY,KAIhB,oBACI,MAAO,IAGX,sBACI,gBAAiB,KACjB,YAAa,EAGjB,cACI,aAAc,QAIlB,iCACI,QAAS"
}
Version from my package.json:
"grunt-contrib-cssmin": "^0.12.0",
What am I doing wrong?
Edit: Firstly, try specifying a root
in your options
of the Gruntfile.js
as follows:
// ...
cssmin: {
options: {
// ...
root: 'web/assets/dist/css/' // <-- Add this too.
},
target: {
// ...
}
/...
The sourceMap file that grunt-contrib-cssmin
is generating is incorrectly specifying the paths in the sources
Array. The resultant sourceMap should be as follows:
app.min.css.map
{
"version":3,
"sources":[
"../../../../app/Resources/assets/css/jumbotron-narrow.css",
"../../../../app/Resources/assets/css/custom.css"
],
"names":[],
"mappings":"AAeA,QAdA,KAeI,eAAgB,KADpB,QA6BA,WAEI,cAAe,IAAI,MAAM,QA7C7B,KACI,YAAa,KCUb,YAAa,eAAkB,WDHnC,QAFA,QACA,WAEI,cAAe,KACf,aAAc,KASlB,WACI,WAAY,EACZ,cAAe,EACf,YAAa,KAIjB,QACI,YAAa,KACb,MAAO,KACP,WAAY,IAAI,MAAM,QAI1B,yBACI,WACI,UAAW,OAGnB,qBACI,OAAQ,KAAK,EAIjB,WACI,WAAY,OAGhB,gBACI,QAAS,KAAK,KACd,UAAW,KAIf,WACI,OAAQ,KAAK,EAEjB,gBACI,WAAY,KAIhB,oCAII,QAFA,QACA,WAEI,cAAe,EACf,aAAc,EAGlB,QACI,cAAe,KAGnB,WACI,cAAe,GC3EvB,WACI,YAAa,eACb,IAAK,iCAAkC,mBAG3C,WACI,YAAa,YACb,IAAK,8BAA+B,mBAOxC,GACI,WAAY,KACZ,eAAgB,UAChB,YAAa,EACb,YAAa,YAAe,WAC5B,YAAa,EAAI,EAAI,IAAI,KAG7B,4BACI,QAAS,MACT,YAAa,KACb,aAAc,KACd,cAAe,IAGnB,UACI,UAAW,MACX,WAAY,KAIhB,oBACI,MAAO,IAGX,sBACI,gBAAiB,KACjB,YAAa,EAGjB,cACI,aAAc,QAIlB,iCACI,QAAS"
}
Note the sourceRoot prefixes ../../../../
added to each path in the sources
Array.
In the SourceMap Specification a section reads:
Resolving Sources
If the sources are not absolute URLs after prepending of the “sourceRoot”, the sources are resolved relative to the SourceMap (like resolving script src in a html document).
If specifying a root
path, (as initially mentioned), does not resolve the issue then it indicates that this part of the specification is not being honoured by grunt-contrib-cssmin
.
If the initial suggested fix does not work then consider adding a custom Task to invoke a Function which fixes each sources
path after the sourceMap(s) have been created by grunt-contrib-cssmin
.
You could do something like this:
Gruntfile.js
module.exports = function (grunt) {
grunt.initConfig( {
cssmin: {
options: {
report: 'gzip',
keepSpecialComments: 0,
sourceMap: true,
outputSourceFiles: true
},
target: {
files: {
'web/assets/dist/css/vendors.min.css': [
'bower_components/bootstrap/dist/css/bootstrap.min.css',
'bower_components/chosen/chosen.min.css',
'bower_components/slabText/css/slabtext.css',
'bower_components/video.js/dist/video-js.css'
],
'web/assets/dist/css/app.min.css': [
'app/Resources/assets/css/jumbotron-narrow.css',
'app/Resources/assets/css/custom.css'
]
}
}
}
});
/**
* Helper function prefixes sources paths in sourceMap files with a sourceRoot.
*
* `grunt-contrib-cssmin` does not apply the correct sourceRoot for each
* path in the `sources` Array. See github issue #248 for further info:
* (https://github.com/gruntjs/grunt-contrib-cssmin/issues/248)
*
* @param {String} filePath - The path to the sourceMap to fix.
* @param {String} sourceRootPrefix - The sourceRoot prefix e.g. ../../
*/
function prefixSourceMap(filePath, sourceRootPrefix) {
var json = grunt.file.readJSON(filePath);
json.sources = json.sources.map(function (_path) {
return sourceRootPrefix + _path;
});
grunt.file.write(filePath, JSON.stringify(json));
}
// Register Task to invoke function for fixing paths in each sourceMap file.
grunt.registerTask('fixSourceMaps', 'Fix paths in each sourceMap', function () {
prefixSourceMap('web/assets/dist/css/vendors.min.css.map', '../../../../');
prefixSourceMap('web/assets/dist/css/app.min.css.map', '../../../../');
});
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.registerTask("default", [
'cssmin',
'fixSourceMaps' // <-- Must be after cssmin tasks.
]);
};
Notes
The the custom grunt.registertask named fixSourceMaps
invokes the prefixSourceMap
function for each sourceMap file to fix.
Two arguments are passed to the prefixSourceMap
function, namely:
filePath
- The path to the sourceMap to fix.sourceRootPrefix
- The sourceRoot prefix e.g. ../../
For fixing both sourceMap files (vendors.min.css.map
and app.min.css.map
) the sourceRootPrefix
argument is specified as ../../../../
- This is specified as four levels due to the relationship between the resultant .min.css
file and it's location to the original unminified source .css
file within your directory structure.
If you were to add another set of .css
files to minify to your cssmin.target.files
Task, in which the relationship between the resultant .min.css
file and the unminified source .css
file was not four levels, you will need to specify a different sourceRootPrefix
value.
For example, lets say in cssmin.target.files
the following css is to be minified:
// ...
target: {
files: {
//...
'web/assets/quux.min.css': [ // <-- Two levels deep
'path/to/file/foo.css',
'path/to/file/baz.css'
],
// ...
}
}
// ...
As the resultant quux.min.css
is saved in the directory two levels deep then the sourceRootPrefix
argument is passed to the prefixSoureMap
functions as '../../'
. For example:
//...
grunt.registerTask('fixSourceMaps', 'Fix paths in each sourceMap', function () {
prefixSourceMap('web/assets/quux.min.css.map', '../../');
//...
});
//...