Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Grunt watch pattern.indexOf is not a function

I'm trying to use Grunt's grunt-contrib-watch plugin to watch some files and then run the tasks, just what it was made for, this is my Gruntfile.js

module.exports = function(grunt){
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        sass: {
            options: {
                sourceMap: true,
                outputStyle: 'compressed'
            },
            dist: {
                files: {
                    'static/stylesheets/main.min.css': 'static/stylesheets/sass/main.scss',
                    /*'bower_components/foundation-sites/dist/foundation.min.css': 'bower_components/foundation-sites/scss/foundation.scss'*/
                }
            }
        },
        uglify: {
            dist: {
                files: {
                    'static/javascript/main.min.js': 'static/javascript/main.js'
                }
            }
        },
        watch: {
            files: [
                '<%= sass.dist.files %>',
                '<%= uglify.dist.files %>'
            ],
            tasks: [
                'sass',
                'uglify'
            ]
        }
    });

    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-sass');
    grunt.loadNpmTasks('grunt-contrib-uglify');

    grunt.registerTask('default', ['watch']);
};

When I run it, it runs over and over and over again, and when I stop it, I see I have this message:

Running "watch" task Waiting... Warning: pattern.indexOf is not a function

I really don't know what's the problem. Does anybody know what happens here?

UPDATE:

Apparently, the problem is because of the way I call the files, because I changed it to: 'static/stylesheets/sass/*.scss' and it worked well, but I would like to know why the other way doesn't work, because I think is a more useful way to do it.

like image 304
Andrés Orozco Avatar asked Aug 28 '16 06:08

Andrés Orozco


2 Answers

grunt-contrib-watch expects either a single pattern string or an array of pattern strings as the value of its files config. However, the templates you are using in your config evaluate to objects. Your watch.files value evaluates to the following:

files: [
    { 'static/stylesheets/main.min.css': 'static/stylesheets/sass/main.scss' },
    { 'static/javascript/main.min.js': 'static/javascript/main.js' }
]

When the pattern matching tries to run it fails because there is no indexOf method on an Object. Due to the fact that grunt-contrib-watch runs forever, there is an infinite loop of the trying and failing to build the list of watched files.

You would normally configure your watch files with something like the following:

files: [
    'static/**/*.scss',
    'static/**/*.js'
]

But the above will cause issues in your case because your minified JS file is in the same folder as your source JS file. You could probably get around this by adding '!static/**/*.min.js' to your files array, but a better solution would be to put all of your compiled files into a separate folder.

like image 192
76484 Avatar answered Oct 02 '22 13:10

76484


Extract the values from the object:

watch: {
    files: [
        '<%= sass.dist.files.values() %>',
        '<%= uglify.dist.files.values() %>'
    ],
like image 45
Ariel Avatar answered Oct 02 '22 13:10

Ariel