-->

Grunt doesn't update main scss file

2019-02-14 01:31发布

问题:

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