问题
I have a project that uses GruntJS with grunt-contrib-sass, grunt-contrib-watch and grunt-newer.
My main app.scss file imports a few .scss files with the @import directive like
@import "common/vars.scss";
If I make changes in the main app.scss everything works. The problem is that when I make changes in a file that is being imported (like vars.scss), the app.scss doesn't get updated.
This is my watch task:
watch: {
css: {
files: ['scss/**/*.scss'],
tasks: ['newer:sass'],
options: {
spawn: false,
}
}
}
And this is the sass task itself:
sass: {
dist: {
options: {
style: 'compressed',
noCache: true
},
/* looks for every .scss file in the scss folder (checks nested folders too),
* compile it and create another file wit the same name in the style folder */
files: [{
expand: true,
cwd: 'scss',
src: ['**/*.scss'],
dest: 'style',
rename: function (dest, src) {
var folder = src.substring(0, src.lastIndexOf('/'));
var filename = src.substring(src.lastIndexOf('/'), src.length);
filename = filename.substring(0, filename.lastIndexOf('.'));
return dest + '/' + folder + filename + '.css';
}
}]
}
}
Any idea how to change the Gruntfile.js to cover this scenario too? :) Thanks.
回答1:
Note: This is a minimally modified copy of this comment in an issue on the grunt-newer GitHub page.
I came up with this simple delegation task that does the trick for tasks where you would like to react to changes other than specified in the src
property:
grunt.initConfig( {
delegate: {
some_other_TASK: {
src: [ 'some/src/path/**/*.ext' ],
dest: 'some/dest/path/'
}
}
} );
grunt.registerTask( 'delegate', function() {
grunt.task.run( this.args.join( ':' ) );
} );
A complete example for grunt-contrib-sass would look like the following:
module.exports = function( grunt ) {
require( 'load-grunt-tasks' )( grunt );
grunt.initConfig( {
delegate: {
sass: {
src: [ 'scss/**/*.scss' ],
dest: 'style'
}
},
sass: {
dist: {
options: {
style: 'compressed',
noCache: true
},
files: [{
expand: true,
cwd: 'scss',
src: ['*.scss'],
dest: 'style',
ext: '.css'
}]
}
}
} );
grunt.registerTask( 'delegate', function() {
grunt.task.run( this.args.join( ':' ) );
} );
};
You just have to call newer:delegate:sass
(via CLI, or some other task). grunt-newer
checks the files given in the according delegate
target (where I have the globbing pattern **/
included). If there are new files found (also .scss
files in subfolders), the according sass
task (with the given target) will be called.
I'm unsure, though, if making a separate grunt plugin would be of use here.
Edit: I recently released the above code (cleaned up) as separate npm package grunt-delegate.
回答2:
I think your watch tasks
variable is backwards, you can check by opening terminal, going to the directory you would normally run grunt watch
but try running newer:sass
if that doen't work, try sass:newer
if the later works change that line in your watch settings.
Also, if you only have one sass task you can just change it to:
watch: {
css: {
files: ['scss/**/*.scss'],
tasks: ['sass']
options: {
spawn: false
}
}
}
Just as a side note, it seems that your sass has needlessly complicated rename function, if you're just trying to take scss/**/*.scss
and turn them into style/**/*.css
you should be able to use this (taken from the grunt-contrib-sass readme):
grunt.initConfig({
sass: {
dist: {
files: [{
expand: true,
cwd: 'scss',
src: ['**/*.scss'],
dest: 'styles',
ext: '.css'
}]
}
}
});
if you have files that use multiple dots eg: file.src.scss
add extDot: 'last'
to the files array
来源:https://stackoverflow.com/questions/23991940/grunt-doesnt-update-main-scss-file