该如何使用Grunt
一、安装grunt
新建项目
npm init -y
安装grunt
npm i grunt
新建gruntfile.js文件
gruntfile.js文件是Grunt的入口文件,用于定义一些需要Grunt自动执行的任务
需要导出一个函数
此函数接收一个 grunt的形参,内部提供一些创建任务时可以用到的API
二、定义grunt任务
// gruntfile.js
module.exports = grunt =>{
// registerTask定义一个任务,调用方法就是 yarn grunt foo,npm需要配置 npm scripts
grunt.registerTask("foo",()=>{
console.log('hello grunt');
})
// 如果第二个参数是字符串的话,会设置为对该任务的描述,可以通过 yarn grunt --help 查看,在其中有个Available tasks,定义的任务都在其中
grunt.registerTask("bar",'任务描述',()=>{
console.log("this is bar");
})
// 如果任务名设置为default,这将会成为grunt的默认任务,在运行这个任务的时候就不需要指定任务名,yarn grunt,grunt将自动调用default
// grunt.registerTask('default',()=>{
// console.log('default task!!');
// })
// 一般我们会用default去映射一些其他的任务,具体做法就是第二个参数传入一个数组,
grunt.registerTask('default', ['foo', 'bar'])
// grunt的代码默认支持同步模式,如果需要异步操作,必须要使用this的async方法,得到一个回调函数,在异步操作完成之后去调用这个回调函数,标识这个任务已经完成
grunt.registerTask('async-task',function(){
const done = this.async()
setTimeout(()=>{
console.log("async task finished");
done() // 实际上没有调用 done(),两秒后也会结束这个任务的执行,具体区别在下面的标记错误有描述
},2000)
})
}
三、grunt标记错误失败
普通任务通过return false标记错误,异步任务通过done(false)
也可以通过 --force强制执行任务,即其中任务失败也会继续向下执行
module.exports = grunt =>{
grunt.registerTask("one", ()=>{
console.log('this is one');
})
grunt.registerTask("two", ()=>{
console.log("this is two");
// return false;
})
grunt.registerTask("three",()=>{
console.log("this is three");
})
grunt.registerTask('async-task',function(){
const done = this.async()
setTimeout(()=>{
console.log("async task finished");
// 在没有通过done()标识任务完成的情况下,如果后面还有任务,后面的任务将不会执行,类似于done(false),但不会有错误标记
done()
// done(false)
// 总结:done()的任务主要是区分异步任务,保证后续任务的继续执行
},2000)
})
// 执行全部任务
grunt.registerTask('all', ['one', 'two', 'async-task', 'three'])
}
执行任务
yarn grunt all // yarn grunt all --force
四、grunt配置选项
grunt还提供了一个用于去添加一些配置选项的API,即initConfig
module.exports = grunt =>{
// initConfig接收一个对象类型的参数,对象的属性名一般与任务名对应,保持一致,属性的值可以是任意类型的数据
grunt.initConfig({
// foo:"this is foo"
foo:{
bar: "this is bar",
age: 18
}
})
grunt.registerTask('foo',() => {
// 我们可以通过grunt的config方法获取配置
// console.log(grunt.config('foo'));
// 如果配置的属性值是对象类型,也可以通过 . 的方式获取值
console.log(grunt.config('foo.age'));
// 通过定义变量接收整个对象数据也是可行的
const data = grunt.config("foo")
console.log(data.bar)
})
}
五、多目标任务
grunt支持一种多目标模式的任务
module.exports = grunt => {
// 在设置多目标任务时我们需要去为多目标任务去配置不同的目标,配置方式就是通过initConfig去配置
grunt.initConfig({
// 属性值必须是对象类型,键名必须对应任务名
build:{
// 我们在build当中指定的每一个属性的键都会成为一个目标,除了options,在options中指定的信息会作为任务的配置选项出现
options:{// 在执行的任务中可以通过this.options()获取
foo:'123456'
},
css: {
// 在目标当中也可以配置options,目标当中配置的options会覆盖任务的配置选项(目标中的配置选项的属性名 与 任务配置选项内的属性名不一致时会一起返回)
options:{
bar:'666666',
foo:'911911'
}
},
js: 2
}
})
// 多目标模式,可以让任务根据配置形成多个子任务
// 第一个参数是任务名称
// 第二个参数是一个函数
grunt.registerMultiTask("build", function(){
// console.log('build task');
// 通过this.options获取配置选项
console.log(this.options());
// 通过this.target拿到当前执行的目标名称,通过this.data拿到当前执行目标对应的数据
// console.log(`target ${this.target} ${this.data}`);
})
}
// yarn grunt build 运行多目标任务
// yarn grunt build:css / yarn grunt build:js 运行指定目标
六、grunt插件的使用
6.1、grunt-contrib-clean
使用 grunt-contrib-clean 插件清除临时文件
安装插件
yarn add grunt-contrib-clean
加载插件
module.exports = grunt => {
// 通过grunt.loadNpmTasks 方法去加载插件中提供的一些任务
grunt.loadNpmTasks("grunt-contrib-clean")
// 绝大多数情况下,grunt插件的命名规范都是 grunt-contrib-<taskName>
// 所以我们要运行任务应该就是yarn grunt clean
}
运行插件
yarn grunt clean
报错了
从报错内容可以看出,clean任务是一个多目标任务,而此时没有设置目标,所以我们需要通过grunt.initConfig去设置任务目标
module.exports = grunt => {
grunt.initConfig({
clean:{
temp:'temp/app.js', //设置clean任务的目标temp,以及temp目标要清除的文件路径
temp2:"temp/*.txt" // 还可以使用通配符的方式去匹配所有对应类型的文件
temp3:"temp/**" // 清空temp下所有的子目录以及子目录下的文件,如此temp下所有的文件都会被清空
}
})
grunt.loadNpmTasks("grunt-contrib-clean")
}
运行
yarn grunt clean
成功清除temp下的文件,可以自己在根目录下创建一个temp目录并创建一些文件测试代码。
6.2、grunt-sass
grunt-sass需要有一个sass的模块支持,所以还需要安装一个sass模块
yarn add grunt-sass sass --dev
使用方法
const sass = require("sass")
module.exports = grunt => {
grunt.initConfig({
sass:{
options:{
sourceMap: true, // 编译过程当中就会自动生成对应的sourceMap文件
implementation: sass // 配置编译模块
},
main:{ // main当中需要指定sass的输入文件以及输出的css路径
files: {
"dist/css/main.css":"src/scss/main.scss"
}
}
}
})
// 载入grunt-sass
grunt.loadNpmTasks("grunt-sass")
}
6.3、grunt-babel
yarn add grunt-babel @babel/core @babel/preset-env --dev
随着我们安装加载的插件越来越多,我们可以安装一个模块帮助我们减少loadNpmTasks的使用
yarn add load-grunt-tasks --dev
const loadGruntTasks = require("load-grunt-tasks")
module.exports = grunt => {
grunt.initConfig({
babel:{
options:{
sourceMap: true, // 编译过程当中就会自动生成对应的sourceMap文件
presets:['@babel/preset-env'] // 这样就能把最新的ES特性全部加载进来
},
main:{
files:{
'dist/js/index.js':'src/js/index.js'
}
}
}
})
// loadGruntTasks会自动加载所有的grunt插件中的任务
loadGruntTasks(grunt)
}
运行yarn grunt babel
即可将ES新特性内容转换为对应的ES5内容
6.4、grunt-contrib-watch
grunt-contrib-watch 模块能帮我们在修改文件后自动去编译
yarn add grunt-contrib-watch --dev
使用
const loadGruntTasks = require("load-grunt-tasks")
const sass = require("sass")
module.exports = grunt => {
grunt.initConfig({
sass:{
options:{
sourceMap: true, // 编译过程当中就会自动生成对应的sourceMap文件
implementation: sass
},
main:{ // main当中需要指定sass的输入文件以及输出的css路径
files: {
"dist/css/main.css":"src/scss/main.scss"
}
}
},
babel:{
options:{
sourceMap: true, // 编译过程当中就会自动生成对应的sourceMap文件
presets:['@babel/preset-env'] // 这样就能把最新的ES特性全部加载进来
},
main:{
files:{
'dist/js/index.js':'src/js/index.js'
}
}
},
watch:{
js:{
files:['src/js/*.js'],// 监听文件
tasks: ['babel']// 指定运行任务
},
css:{
files:['src/scss/*.scss'],// 监听文件
tasks: ['sass'] // 指定运行任务
}
}
})
// loadGruntTasks会自动加载所有的grunt插件中的任务
loadGruntTasks(grunt)
grunt.registerTask('default',['sass', 'babel', 'watch'])
}
由于这里我们用default去映射其他的任务,只需要执行yarn grunt
,就会按sass、babel、watch的顺序去执行。