LeoYuan / leoyuan.github.io

This is my blog repo.
http://leoyuan.github.io
17 stars 2 forks source link

Grunt学习笔记 #3

Open LeoYuan opened 11 years ago

LeoYuan commented 11 years ago

初识Grunt

Grunt为何物?能灭活H7N9病毒?能稳固海沙楼?能降PM2.5?抱歉,都不能。 那它到底是啥?其实就是一个类似Maven的任务运行器(task runner),想要完成的核心目标就是自动化,帮助开发人员解决项目中手工操作繁琐的痛点,比如js静态检查、压缩、打包、部署等操作。

怎么用?

简单的说就是如下几步,

  1. 安装nodejs;
  2. 安装grunt-cli;
  3. 配置Gruntfile.js,里边包括运行插件模块和注册任务集;
  4. 运行grunt taskName即可完成你配置的taskName任务集; 详细的请看官网Getting Started

    Grunt API

Grunt提供的API数量不多,除了几个核心的外,其他大多是对一些常用操作进行的封装,如读写文件,日志记录,甚至整个underscore的函数都被集成进来了。

  1. grunt.registerTask(taskName, taskDesc, handler); 即注册一个任务集, 无子任务(target) ,注册成功后,可以通过grunt taskName来执行该任务集; 还可以传参数给任务集,如grunt taskName:a:b,这样handler的第一个参数就能取到值a,第二个参数则能取到值b。
  2. grunt.registerMutilTask(taskName, taskDesc, handler); 还是注册一个任务集,不过该任务集下 有子任务,如有如下代码:
module.exports = function(grunt) {
  // Project configuration.
  grunt.initConfig({
    complex: {
      targetA: [1, 2, 3],
      targetB: "string"
    }
  });

  grunt.registerMultiTask('complex', 'complex task', function(a, b) {
    console.log('current target -> ' + this.target);
    console.log('current target data -> ' + this.data);
    console.log('parameters -> ', a, b);
  })
};

运行grunt complex:a:paramA:paramB即可打印出

D:\workspaces\javascript\misc\grunt_test>grunt complex:targetA:paramA:paramB
Running "complex:targetA:paramA:paramB" (complex) task
current target -> targetA
current target data -> 1,2,3
parameters ->  paramA paramB

Done, without errors.

不加这句话,下边的列表就会算成上边的子列表,不知道怎么搞。。。无奈之举

  1. grunt.config.get/set 设置或读取配置项
  2. grunt.event.on/once/many 可以加事件监听,目前我用到的就是grunt-contrib-watch插件emit的watch事件,可以监听到文件的增删改操作,并且获得文件名。
  3. grunt.task.run(taskName) 运行指定的任务集taskName。 以上只列出了常用的API,更详细的列表请参加Grunt API

    遇到的难点

不加这句话,下边的列表就会算成上边的子列表,不知道怎么搞。。。无奈之举

  1. Grunt在设计中鉴于代码简单性采取的是同步执行代码的方式,那假如你的任务是需要异步执行呢? 这时你就需要知会Grunt使用异步方式来执行代码了,具体方式是在任务函数内部使用var done = this.async()来通知Grunt,并且执行done(signal)来通知Grunt异步执行完毕。 示例代码如下
grunt.registerTask('async', 'asynchronous task', function() {
  var exec = require('child_process').exec,
  var cmd = 'rm test.txt';
  var done = this.async();
  exec(cmd, function (error, stdout, stderr) {
    done(true);
  })
});

不加这句话,下边的列表就会算成上边的子列表,不知道怎么搞。。。无奈之举

  1. 任务集之间如何通信 ? 之前遇到一个场景,使用grunt.event.on("watch", function(filepath) {})来监听哪个文件被更改了,然后想通过grunt.task.run(someTask:filepath)来执行另一个任务集,发现任务集不会被调用。 与Grunt的作者交流后得知,事件监听中不支持这样的操作,详细可见Why is grunt.task.run not called in the grunt.event.on("watch") handler?,最后得出的折中方案是在watch事件中使用全局变量记录修改的文件名,然后在另外一个任务集中读取这个全局变量来通信,虽然有点锉,总归是有条路。

    小结

一开始使用Grunt的过程,挫折颇多,如异步问题,跨任务集通信问题,不过最终都得以解决,甚好。总体感觉Grunt这玩意儿还是解放我们双手的利器,右手还得去做点其他事,不是吗?

varfunction commented 11 years ago

最后一句把我晃瞎了~

LeoYuan commented 11 years ago

@varfunction 有位名人曾经说过

习惯,习惯就好