我正在使用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']);
};
答案 0 :(得分:1)
问题出在行上:104,105和116,您在+
之后错过了加号path_dev
:
less['build']['files'][path_live+'/css/global.css'] = path_dev+'/less/main.less';
请你解决其他问题。