自动化构建 -- 一篇文章带你了解Grunt
Grunt怎么使用?
Grunt算是最早的一款前端构建系统了,Grunt的插件生态非常的完善
安装Grunt
yarn add grunt
安装完成后在项目根目录添加Grunt的入口文件gruntfile.js
- Grunt的入口文件
- 用于定义一些需要 Grunt 自动执行的任务
- 需要导出一个函数
- 此函数接收一个 Grunt 的形参,内部提供一些创建任务可以用到的 API
Grunt 任务注册
Grunt 使用接口registerTask来注册任务
module.exports=grunt=>{
// 注册任务
grunt.registerTask('foo',()=>{
console.log('hello grunt~')
})
// 注册默认任务
grunt.registerTask('default',()=>{
console.log('default task~')
})
}
执行grunt任务
yarn grunt bar
执行结果如下:
默认任务不需要指定任务名
yarn grunt
执行结果如下:
Grunt的Default任务
一般注册default任务来映射其它任务
// default的任务的第二个参数传入一个数组,数组中是要执行的其它的任务,执行default任务会依次执行数组中的任务
grunt.registerTask('default',['foo','bar'])
此时运行default任务结果如下图所示:
Grunt 的异步任务
Grunt默认使用同步模式,要使用异步操作,需要在任务中使用this.async() 来得到一个回调函数,并在异步操作完成后执行此回调,不然异步操作不会得到执行,此任务的回调函数不能是箭头函数
grunt.registerTask('async-task', function(){
const done=this.async()
setTimeout(()=>{
console.log('async task working...')
done()
},1000)
})
Grunt标记任务失败
任务失败时,需要在任务中返回false来标记任务失败,执行多个任务时,当有任务失败了,后续任务就不会再执行了,可以根据提示添加force参数来让任务保持继续执行
grunt.registerTask('badtask',()=>{
console.log('badtask working')
return false
})
grunt.registerTask('default',['foo','badtask','bar'])
运行default失败的任务结果如下:
从图中可以看到,foo任务执行了,但bar任务没有任务
尝试添加--force强制不打断执行:
此时bar任务也执行了
Grunt 标记异步任务的失败
异步任务不能像同步任务一样直接返回false,需要在this.async()中传入参数false
grunt.registerTask('async-badtask',function(){
const done=this.async()
setTimeout(() => {
console.log('async bad')
done(false)
}, 1000);
})
Grunt 的配置选项
Grunt 提供一个API叫initConfig,用来添加一些配置选项,选项名一般与任务名保持一致,选项值可以是值,也可以是对象,具体看代码:
grunt.initConfig({
foo:'bar',
objtest:{
prop1:1232,
objprop:{
foo:'111'
}
}
})
grunt.registerTask('objtest',()=>{
// 配置选项为对象时可以通过"."语法拿到子属性
console.log(grunt.config('objtest.objprop.foo'))
})
grunt.registerTask('foo',()=>{
console.log(grunt.config('foo'))
})
grunt.registerTask('default',['foo','objtest'])
})
运行结果如下:
Grunt 的多目标任务
Grunt注册的任务可以根据配置形成多个子任务
为任务配置多个目标:
grunt.initConfig({
// 为multiTask任务配置的多个目标
multiTask:{
css:'1',
js:'2'
}
})
注册多目标任务:
//使用registerMultiTask注册多目标任务
grunt.registerMultiTask('multiTask',function(){
// 可以通过this.target拿到目标的名称,this.data拿到目标的数据
console.log(`target:${this.target},data:${this.data}`)
})
multiTask 运行结果:
从上图可以看到多个目标都被执行了,当我们只想执行指定目标时,通过冒号+目标名来执行指定的目标
注意:多目标任务不会对配置选项中的options进行执行,如下所示:
// initConfig中的配置选项
grunt.initConfig({
multiTask:{
options:{
foo:'bar',
},
css:'1',
js:'2'
}
})
grunt.registerMultiTask('multiTask',function(){
console.log(`target:${this.target},data:${this.data}`)
})
执行multiTask任务结果:
可以看出,options中的配置没有对应的执行输出
配置的目标中也有options时,会覆盖外层的options的对应属性
grunt.initConfig({
multiTask:{
options:{
foo:'bar',
},
css:{
options:{
// 当执行css目标时,此foo会覆盖外层foo
foo:'baz'
}
},
js:'2'
}
})
grunt.registerMultiTask('multiTask',function(){
console.log(this.options())
})
执行multiTask结果:
css对应输出{foo:baz}
js对应输出{foo:bar}
grunt-contrib-clean插件 删除文件
-
Grunt的插件多数都是以grunt-contrib-
的形式来名称的,比如grunt-contrib-clean就等于是clean任务,执行的时候只需要执行类似 yarn grunt clean
就可以了,同时它的配置选项名也只需要写clean就可以了 -
grunt-contrib-clean插件用于清除文件,其是一个多目标任务,需要对其配置多目标选项,不然会执行会产生错误提示
-
安装grunt-contrib-clean插件
yarn add grunt-contrib-clean
- 加载任务
grunt.initConfig({
clean:{
// 表示将会删除temp目录中的app.js文件
// 除了单文件外,还可以批量删除文件,
// 使用temp/*.txt来删除temp目录下以所有的txt文件
// 使用temp/** 来删除temp目录以及temp里面的所有内容
temp:'temp/app.js'
}
})
grunt.loadNpmTasks('grunt-contrib-clean')
- 执行任务
yarn grunt clean
grunt-sass插件处理sass
- 安装依赖
yarn add grunt-sass sass --dev
- 配置目标
const sass=require('sass')
module.exports=grunt=>{
grunt.initConfig({
sass:{
options:{
sourceMap:true,
implementation:sass
// 更多选项可以到grunt-sass的官方仓库查看
},
main:{
files:{
'dist/css/main.css':'src/scss/main.scss'
}
}
}
})
grunt.loadNpmTasks('grunt-sass')
}
load-grunt-tasks 插件自动加载
加载grunt插件的npm包,我们可以使用grunt.loadNpmTasks('插件名')来加载插件,当插件很多时,其实不需要每个插件都手动加载一遍,可以使用grunt提供的loadGruntTasks方法,这个方法可以自动的为我们加载需要的插件
只需要将grunt对象传入作为参数就可以了:loadGruntTasks(grunt)
grunt-babel 编译es6语法
- 安装依赖
yarn add grunt-babel @babel/core @babel/preset-env --dev
- 配置目标
const loadGruntTasks=require('load-grunt-tasks')
module.exports=grunt=>{
grunt.initConfig({
babel:{
options:{
sourceMap:true,
presets:['@babel/preset-env']
},
main:{
files:{
'dist/js/app.js':'src/js/app.js'
}
}
}
})
loadGruntTasks(grunt) //自动加载所有的grunt插件中的任务
}
grunt-contrib-watch监听文件变化
-
安装:
yarn add grunt-contrib-watch --dev
-
目标配置
const loadGruntTasks=require('load-grunt-tasks')
module.exports=grunt=>{
grunt.initConfig({
watch:{
js:{
// 监听的文件
files:['src/js/*.js'],
// 文件发生改变时需要执行的任务
tasks:['babel']
},
css:{
// 监听的文件
files:['src/scss/*.scss'],
// 文件发生改变时需要执行的任务
tasks:['sass']
}
}
})
loadGruntTasks(grunt) //自动加载所有的grunt插件中的任务
// 因为watch任务只在目标文件发生变动时才会执行相关任务,若要一开始就执行相关任务,可以为相关任务做一个映射,使watch监听开始前就先执行一遍相关任务
grunt.registerTask('default',['sass','babel','watch'])
}
运行yarn grunt
就可以开启watch监听了