自动化构建 -- 一篇文章带你了解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监听了

posted @ 2021-06-20 03:10  MissSage  阅读(95)  评论(0编辑  收藏  举报