Grunt:获取错误的行号

Grunt: get line numbers for errors

我将 Grunt 与 node.js 一起使用,并试图让 Grunt 告诉我它在 Gruntfile.js 中发现错误的位置。默认情况下它不会这样做似乎很奇怪。

对于 grunt watch,我收到此错误:

Loading "Gruntfile.js" tasks...ERROR
>> SyntaxError: Unexpected string
Warning: Task "watch" not found. Use --force to continue.

我真的很想知道意外字符串在哪一行,但我无法让 Grunt 告诉我。

当我尝试 grunt watch --stack 时,它显示了节点文件的整个 node.js 堆栈跟踪,但没有显示 Gruntfile.js.

中的错误来源

按照 this answer 中的建议,将 grunt.option('stack', true); 添加到 Gruntfile.js 的顶部,但没有任何效果。

我的Gruntfile.js:

var path_dev = 'app/assets/_dev';
var path_live = 'app/assets'; 
var url_dev = '//assets.domain.dev/_dev';

module.exports = function (grunt) {
    grunt.option('stack', true);
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        banner: '/*!\n' +
                '* <%= pkg.name %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %> - Copyright <%= grunt.template.today("yyyy") %> \n' +
                '* @author <%= pkg.author %>\n' +
                '*/',

        path_dev: path_dev,
        path_live: path_live,
        url_dev: url_dev,

        clean: {
            build: {
                src: [
                    '<%= path_live %>/css/',
                    '<%= path_live %>/js/'
                ]
            }
        },

        concat: {
            options: {
                separator: ';'
            },
            build: {
                src: [
                    '<%= path_dev %>/js/core/jquery.min.js',
                    '<%= path_dev %>/js/core/bootstrap.min.js',
                    '<%= path_dev %>/js/core/jquery.slimscroll.min.js',
                    '<%= path_dev %>/js/core/jquery.scrollLock.min.js',
                    '<%= path_dev %>/js/core/jquery.appear.min.js',
                    '<%= path_dev %>/js/core/jquery.countTo.min.js',
                    '<%= path_dev %>/js/core/jquery.placeholder.min.js',
                    '<%= path_dev %>/js/core/js.cookie.min.js',
                    '<%= path_dev %>/js/main.js'
                ],
                dest: '<%= path_live %>/js/global.js'
            }
        },

        uglify: {
            options: {
                banner: '<%= banner %>'
            },
            build: {
                files: {
                    '<%= path_live %>/js/global.js': ['<%= path_live %>/js/global.js']
                }
            }
        },

        copy: {
            build: {
                files: [
                    {
                        expand: true,
                        cwd: '<%= path_dev %>/css/',
                        src: 'bootstrap.min.css',
                        dest: '<%= path_live %>/css/'
                    },
                    {
                        expand: true,
                        cwd: '<%= path_dev %>/fonts/',
                        src: '**',
                        dest: '<%= path_live %>/fonts/'
                    },
                    {
                        expand: true,
                        cwd: '<%= path_dev %>/img/',
                        src: '**',
                        dest: '<%= path_live %>/img/'
                    },
                    {
                        expand: true,
                        cwd: '<%= path_dev %>/js/plugins/',
                        src: '**',
                        dest: '<%= path_live %>/js/plugins/'
                    }
                ]
            }
        }
    });

    var tasks_to_watch = [];
    var less = {}; 
    var watch = {};


    //less:build
    less['build'] = {
        options: {
            compress: true,
            yuicompress: true,
            optimization: 2,
        },
        files: {}
    };
    less['build']['files'][path_live+'/css/global.css'] = path_dev'/less/main.less';
    less['build']['files'][path_live+'/css/apps/**/*.css'] = path_dev'/less/apps/**/*.less';


    //less:dev_main
    less['dev_main'] = {
        options: {
            sourceMap: true,
            sourceMapURL: url_dev+'/css/global.css.map',
        },
        files: {}
    };
    less['dev_main']['files'][path_dev+'/css/global.css'] = path_dev'/less/main.less'; 

    tasks_to_watch.push('less:dev_main');



    //less:(dynamically find .less files)
    grunt.file.recurse(path_dev+'/less/apps/', function(abspath, rootdir, subdir, filename) {

        if(filename.match(/\.less$/g)){
            var name = filename.substring(0, filename.lastIndexOf('.'));
            var thisurl = url_dev+'/css/apps/app/'+name+'.css';
            var thispath = path_dev+'/css/apps/app/'+name+'.css';

            less[name] = {
                options: {
                    sourceMap: true, 
                    sourceMapURL: thisurl+'.map',
                }, 
                files: {}
            };
            less[name]['files'][thispath] = abspath;
            tasks_to_watch.push('less:'+name);
        }
    }); //grunt.file.recurse()


    watch = {
        styles: {
            files: [path_dev+'/less/**/*.less'],
            tasks: tasks_to_watch,
            options: {
                nospawn: true
            }
        }
    };

    //now repurpose the array to contain all tasks, so we can register them all below
    tasks_to_watch.push('less:build');
    tasks_to_watch.push('watch');

    //load tasks
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-contrib-less');
    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-copy');

    grunt.config('less', less);
    grunt.config('watch', watch);

    //register tasks
    grunt.registerTask('default', tasks_to_watch);
    grunt.registerTask('build', ['clean:build', 'less:build', 'concat:build', 'uglify:build', 'copy:build']);
};

问题在第 104、105 和 116 行,您错过了 path_dev 后的加号 +:

less['build']['files'][path_live+'/css/global.css'] = path_dev+'/less/main.less';

其他的请给你解决。