自动化构建 -- Grunt

Posted MissSage

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自动化构建 -- 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监听了

以上是关于自动化构建 -- Grunt的主要内容,如果未能解决你的问题,请参考以下文章

自动构建 grunt gulp

自动构建 grunt gulp

grunt自动化构建工具

前端自动化构建工具Grunt

前端工作流程自动化——Grunt/Gulp 自动化

Grunt构建工具