gruntjsgrunt-contrib-watch

Different Grunt watch tasks and triggering events


I try to use two watch tasks, one for HTML and CSS which (should) just trigger a reload (which does not happen either) and another one which is triggered by .js files. In an event I then try to just uglify the file that changed, and then concatenate all the .js files.

It does not work. All the time, all js files are uglified, no matter which file changes. Is there a solution?

module.exports = function(grunt) {

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    concat: {
      options: {
        separator: ';'
      },
      files: {
        src: ['js/minified/jquery.min.js',
          'js/minified/jquery-migrate.min.js',
          'js/minified/jquery-ui-1.10.3.custom.min.js',
          'js/minified/jquery.imagesloaded.min.js',
          'js/minified/video.js',
          'js/minified/bigvideo.js',
          'js/minified/jquery.cycle.all.js',
          'js/minified/jquery.maximage.js',
          'js/minified/jquery.jfeed.js',
          'js/minified/moment.min.js',
          'js/minified/fastclick.js',
          'js/minified/cookies.min.js',
          'js/minified/jquery.hammer.min.js',
          'js/minified/index.js'
        ],
        dest: '<%= pkg.name %>.js'
      },
    },
    uglify: {
      files: {
        src: 'js/*.js', // Source files mask
        dest: 'js/minified', // Destination folder
        expand: true, // Allow dynamic building
        flatten: true, // Remove all unnecessary nesting
      }
    },
    jshint: {
      files: ['gruntfile.js', 'js/index.js'],
      options: {
        // Options here to override JSHint defaults
        globals: {
          jQuery: true,
          console: true,
          module: true,
          document: true
        }
      }
    },
    watch: {
      options: {
        livereload: true
      },
      javascript: {
        files: ['js/*.js', 'gruntfile.js'],
        tasks: ['watchtask'],
        options: {
          nospawn: true,
        }
      },
      therest: {
        files: ['index.html', 'css/*.css'],
        tasks: []
      }
    },
    open: {
      dev: {
        path: 'http://127.0.0.1:8000'
      },
    },
    connect: {
      server: {
        options: {
          hostname: '*',
          port: 8000
        }
      }
    }
  });

  grunt.event.on('watch', function(action, filepath) {
    // Change the source in the uglify task at run time so that it affects the changed file only
    grunt.config(['uglify', 'files', 'src'], filepath);
  });

  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-open');

  grunt.registerTask('default', ['jshint', 'uglify', 'concat', 'connect', 'open', 'watch']);
  grunt.registerTask('watchtask', ['jshint', 'uglify', 'concat']);

};

Solution

  • That is expected behavior. When any file changes in the watch:javascript task file list, the associated tasks are executed. Your watchtask runs UglifyJS which uglifies all of the JavaScript code. You would need to specify separate watch targets for different JavaScript files and separate UglifyJS targets to do what you suggest.

    For example:

    ...
      uglify: {
        someTarget: {
          files: {
            src: 'js/file1.js', // source files mask
            dest: 'js/minified', // destination folder
            expand: true, // allow dynamic building
            flatten: true, // remove all unnecessary nesting
          }
        },
        otherTarget: {
          files: {
            src: 'js/file2.js', // source files mask
            dest: 'js/minified', // destination folder
            expand: true, // allow dynamic building
            flatten: true, // remove all unnecessary nesting
          }
        }
      },
      ...
      watch: {
        options: {
          livereload: true
        },
        javascriptOne: {
      files: ['js/file1.js'],
          tasks: ['uglify:someTarget'],
          options: {
            nospawn: true,
          }
        },
        javascriptTwo: {
          files: ['js/file2.js'],
          tasks: ['uglify:otherTarget'],
          options: {
            nospawn: true,
          }
        },
        ...
      },
    ...