当文件被添加、更改或删除时,运行预定义的任务
安装插件
npm install grunt-contrib-watch --save-dev
安装完插件后,可以在Gruntfile中用这行代码启用插件
grunt.loadNpmTasks('grunt-contrib-watch');
可以使用grunt watch
命令启动这个任务
设置
files
类型: String|Array
定义了这个任务将要监视的文件,可以为一个路径字符串或者一个字符串的数组.
tasks
类型: `String|Array`
这定义了当监视的文件事件发生时要运行的任务。
options.spawn
类型:Boolean
默认值:true
默认会创建一个新的子进程来执行触发的任务。通过设置为 false
,可以使得触发的任务可以共享进程上下文,并且提高速度。但是,这会导致监控任务容易崩溃,所以,请尽量使用这个特性,在新的子进程中执行任务。
watch: {
scripts: {
files: ['**/*.js'],
tasks: ['jshint'],
options: {
spawn: false,
},
},
},
options.interrupt
类型:Boolean
默认值:false
在文件发生修改的时候,会生成子进程来执行任务,默认的行为是对于每个目标来说,在上一个处理完成之后,仅仅生成一个新的子进程来执行任务。设置 interrupt
为 true
,将会导致中止上一个进程,生成一个新进程来处理最后的变更。
watch: {
scripts: {
files: '**/*.js',
tasks: ['jshint'],
options: {
interrupt: true,
},
},
},
options.debounceDelay
类型:Integer
默认值:500
如果同样的文件或者路径被修改,需要等待多长时间才触发事件。默认 500 毫秒。
options.event
类型:String|Array
默认值:'all'
指定监控目标的特定事件类型,可以为 'all', 'changed', 'added' 和 'deleted'.
options.reload
类型:Boolean
默认值:false
默认情况下,如果 Gruntfile.js
文件被监控,在这个文件被修改之后,会导致监控任务重新启动。并且重新加载 Gruntfile.js
。
如果 reload
设置为 true
,任何被监控文件的修改都会导致监控任务重新启动。除非你的 Gruntfile.js
依赖于其它文件,否则不使用这个参数。
options.forever
类型:Boolean
默认值:true
这是整个任务级别的参数,不能在单个目标上配置。默认情况下,监控任务会处理 grunt.fatal
和 grunt.warn
,防止导致的退出监控问题。如果你不希望监控任务覆盖 grunt.fatal
和 grunt.warn
,可以将 forever 设置为 false
。
options.dateFormat
类型: Function
这是一个任务级别的参数,不能在单个目标上配置。默认情况下,当watch完成任务时,它将显示消息Completed in 1.301s at Thu Jul 18 2013 14:58:21 GMT-0700 (PDT) - Waiting...
您可以通过提供自己的函数来覆盖此消息:
atch: {
options: {
dateFormat: function(time) {
grunt.log.writeln('The watch finished in ' + time + 'ms at' + (new Date()).toString());
grunt.log.writeln('Waiting for more changes...');
},
},
scripts: {
files: '**/*.js',
tasks: 'jshint',
},
},
options.atBegin
类型:Boolean
默认值:false
此选项将在监视器启动时触发每个指定任务的运行。
options.livereload
类型:Boolean|Number|Object
默认值:false
设置为true
或设置为端口号以启动实时加载,默认和推荐的端口号是35729
如果启用了一个实时重新加载服务器,则将启动每个目标的watch任务。然后在指定的任务运行后,将通过修改的文件触发实时重新加载服务器。
另请参阅如何在HTML上启用livereload。
例:
watch: {
css: {
files: '**/*.sass',
tasks: ['sass'],
options: {
livereload: true,
},
},
},
给livereload
传递一个对象允许侦听特定端口和主机名/ IP或https连接(通过key
和cert
参数 )
options.cwd
类型:String|Object
默认值:process.cwd()
能够设置当前工作目录。默认为process.cwd()
。可以是一个字符串,以设置cwd来匹配文件和生成任务或一个对象来独立设置
ptions: {
cwd: {
files: 'match/files/from/here',
spawn: 'but/spawn/files/from/here'
}
}
在发射事件之前剥离路径:
options: {
cwd: {
files: 'a/path',
event: 'a/path'
}
}
a/path
在发射事件之前将被剥离。此选项对于指定与livereload一起使用的基本目录很有用。
options.livereloadOnError
类型:Boolean
默认值:true
如果执行的任务遇到错误,则可以防止实时重新启动。如果设置为false
,则只有当所有任务成功完成时,才会触发活动载入。
示例
//简单的配置,在任何添加文件,更改或删除的时候运行jshint
grunt.initConfig({
watch: {
files: ['**/*'],
tasks: ['jshint'],
},
});
//高级配置 在添加,更改或删除特定文件时运行特定任务。
grunt.initConfig({
watch: {
gruntfile: {
files: 'Gruntfile.js',
tasks: ['jshint:gruntfile'],
},
src: {
files: ['lib/*.js', 'css/**/*.scss', '!lib/dontwatch.js'],
tasks: ['default'],
},
test: {
files: '<%= jshint.test.src %>',
tasks: ['jshint:test', 'qunit'],
},
},
});
使用watch
事件
watch
当观察文件被修改时,此任务将发出一个事件。如果您希望编辑文件时简单通知,或者如果您正在使用此任务与另一项任务相一致,这将非常有用。以下是使用watch事件的简单示例:
grunt.initConfig({
watch: {
scripts: {
files: ['lib/*.js'],
},
},
});
grunt.event.on('watch', function(action, filepath, target) {
grunt.log.writeln(target + ': ' + filepath + ' has ' + action);
});
watch事件不是用来替换配置和运行标准的Grunt API的,如果尝试从watch事件中执行任务,可能会遇到错误
根据需要编译文件
一个非常普遍的要求是只根据需要编译文件.这里是一个例子,只有改变内容的文件才执行jshint任务:
grunt.initConfig({
watch: {
scripts: {
files: ['lib/*.js'],
tasks: ['jshint'],
options: {
spawn: false,
},
},
},
jshint: {
all: {
src: ['lib/*.js'],
},
},
});
// On watch events configure jshint:all to only run on changed file
grunt.event.on('watch', function(action, filepath) {
grunt.config('jshint.all.src', filepath);
});
如果您需要动态修改配置,则spawn设置为false
,以使watch在相同的上下文下运行。
如果您同时保存多个文件,您可以选择更强大的方法:
var changedFiles = Object.create(null);
var onChange = grunt.util._.debounce(function() {
grunt.config('jshint.all.src', Object.keys(changedFiles));
changedFiles = Object.create(null);
}, 200);
grunt.event.on('watch', function(action, filepath) {
changedFiles[filepath] = action;
onChange();
});
Live Reloading
Live Reloading已经内置在watch任务中.设置选项livereload
,true
使用默认端口35729
或设置为自定义端口:livereload: 1337
。
grunt.initConfig({
watch: {
options: {
livereload: true,
},
css: {
files: ['public/scss/*.scss'],
tasks: ['compass'],
},
},
});
您还可以为单个监视目标配置实时重新载入,或运行多个实时重新加载服务器。只要确定您是否启动在不同端口上运行的多台服务器:
grunt.initConfig({
watch: {
css: {
files: ['public/scss/*.scss'],
tasks: ['compass'],
options: {
// Start a live reload server on the default port 35729
livereload: true,
},
},
another: {
files: ['lib/*.js'],
tasks: ['anothertask'],
options: {
// Start another live reload server on port 1337
livereload: 1337,
},
},
dont: {
files: ['other/stuff/*'],
tasks: ['dostuff'],
},
},
});
在HTML中启用实时重新加载
一旦启动了live reload服务器,就可以访问live reload脚本。在页面上启用实时重新加载,在闭合标签</body>
前面田间一个script标签指向livereload.js
<script src="//localhost:35729/livereload.js"></script>
请随意将此脚本添加到您的模板环境中,并以某种形式的dev
标志进行切换。
使用实时重新加载浏览器扩展
您可以通过安装浏览器扩展程序来重新加载页面,而不是在页面中添加脚本标记。请访问如何安装和使用浏览器扩展来帮助安装浏览器的扩展
。
一旦安装,请使用默认的实时重新加载端口35729
,浏览器扩展将自动重新加载您的页面,而不需要<script>
标签。
使用连接中间件
由于在开发时使用了live reloading,所以您可能想要禁用生成的构建(并且不使用浏览器扩展)。一种方法是使用连接中间件将脚本标签插入到页面中。尝试使用connect-livereload中间件将实时重新加载脚本注入到您的页面中。
封装自己的Live Reload
框架tiny-lr可以很轻松得实现Live reloading,鼓励阅读文档tiny-lr
,如果想自己触发live reload服务,只需将文件POST到URL:http://localhost:35729 /changed
,或者如果你想封装自己的live reload 实现,请使用以下示例:
// Create a live reload server instance
var lrserver = require('tiny-lr')();
// Listen on port 35729
lrserver.listen(35729, function(err) { console.log('LR Server Started'); });
// Then later trigger files or POST to localhost:35729/changed
lrserver.changed({body:{files:['public/css/changed.css']}});