grunt的插件机制

task.loadNpmTasks = function(name) {
  var root = path.resolve('node_modules');
  var tasksdir = path.join(root, packagename, 'tasks');   //加载grunt 插件的tasks
  if (grunt.file.exists(tasksdir)) {
  loadTasks(tasksdir);
  } else {
  grunt.log.error('Local Npm module "' + name + '" not found. Is it installed?');
  }
}

1、插件中使用插件

有时我们需要在插件中使用插件来充分利用package资源, 但是由于插件通常会再被其它package使用,tasksdir通常会定位到使用插件的package下的tasks; 所以就会报错找不到相关packageName的tasks。

那么我们可以通过在插件中重新定义 loadNpmTasks 方法来实现在当前package下加载插件, 如:

//grunt查找插件的规则是通过path.join(G)
var loadNpmTasks = function(name) {
var cwd = process.cwd();
var baseDir = path.resolve(__dirname, '..');
grunt.file.setBase(baseDir);
//packdir必须使用相对路径
grunt.loadNpmTasks(name);
grunt.file.setBase(cwd);
};

2、插件中文件的处理

可以通过 grunt.file.setBase(cwd) 来设计,文件操作的cwd

3、任务名称覆盖问题

如果在插件中使用到一些非常常用的第三方插件, 如grunt-contrib-clean、grunt-contrib-copy等插件,有可能在使用插件的package中也会用到, 所以一定不要覆盖使用插件的package的grunt配置,也不能merge配置, merge会导致执行顺序的修改。

举个例子:

grunt task build 的gruntfile

//package build
grunt.initConfig({
"build-xxx": {
//build-xxx是一个插件提供的task的配置
},
"clean": {
//使用插件 grunt-contrib-clean
}
}); //package build-xxx 中的tasks/build-xxx.js
grunt.registerTask('build-xxx', function() {
//如下会覆盖掉package build中的grunt config clean, 导致task clean不可用。
grunt.initConfig({
"clean": {},
"copy": {}
});
//merge会导致执行顺序被修改
grunt.config.merge({clean: {}}); grunt.task.run(["clean", "copy"])
});

以上两种方式都会导致用户在使用grunt插件时,得到和预期不一致的结果,但是一个好的插件是不应该让使用者关心下层的实现的, so,可以改进如下:

在build-xxx的tasks/build-xxx.js中增加一个cleanConfig的任务
var originGruntConfig = grunt.config.data;
grunt.initConfig({
"clean": {},
"copy": {},
"cleanConfig": {}
});
grunt.registerTask('cleanConfig', function() {
grunt.initConfig(originGruntConfig);
});

为什么要使用新增任务cleanConfig,而不是直接在 grunt.task.run(["clean", "copy"])  执行后将配置修改过来呢, 是因为grunt的run是基于任务队列运行, 不是及时同步完成。  我们需要在run结束后在将原有的config给同步过来。

4、task中的异步处理回调问题

如果在task的function body中存在异步调用,  这个问题和插件开发没什么关心,不过在用grunt写工具时需要注意一下

setTimeout(function() {
console.log('enter');
}, 2000);  

那么在grunt中是默认不会执行的, 原因grunt的tasks 队列运行机制, 队列中的tasks运行完之后会执行exit, 退出当前进程;

do {
thing = this._queue.shift();
} while (thing === this._placeholder || thing === this._marker);
// If queue was empty, we're all done.
if (!thing) {
this._running = false;
if (this._options.done) {
process.exit(0);
}
return;
}
}

可以使用grunt提供的 this.async()方法,  在异步回调结束后调用生成的done行数,已确保该异步调用能在下一个task之前执行, 如:

var done = this.async();
setTimeout(function() {
//do something;
done(true);
}, 2000);

最新文章

  1. 使用KRPano资源分析工具还原全景图片
  2. XCode一直显示"scanning for working copies"的解决办法
  3. tomcat启动后,在普通java类中获取spring管理的bean和ServletContext,(经过验证,可以取到)
  4. 手机端的click
  5. XmlElement 类
  6. linq to sql (Group By/Having/Count/Sum/Min/Max/Avg操作符)
  7. c# 与flash通信简介
  8. 使用CSS达到阴阳八卦图等图形
  9. 基于Socket的UDP和TCP编程介绍
  10. asp之FSO大全
  11. 利用id来进行树状数组,而不是离散化以后的val HDU 4417 离线+树状数组
  12. 个人附加作业XD --这门课终于结束了~~
  13. Python中capitalize()与title()的区别
  14. 201771010126 王燕《面向对象程序设计(Java)》第十六周学习总结
  15. position(3rd week blog)
  16. Archlinux/Manjaro使用笔记-使用makepkg安装软件 报错:未找到strip分割所需的二进制文件 的解决方法
  17. Packt发布了2018年技能提升报告
  18. 剑指offer十九之顺时针打印矩阵
  19. 异步FIFO空满设计延迟问题
  20. S3 exercise -- 文件操作&函数

热门文章

  1. 2、转载一篇,浅析人脸检测之Haar分类器方法
  2. 系统内置委托:Func/Action
  3. package-cleanup
  4. ASP.NET MVC 5使用Swagger生成API文档
  5. 理解纯CSS画三角形
  6. JSON 序列化和解析
  7. MicroPython+北斗+GPS+GPRS:TPYBoardv702短信功能使用说明
  8. SQL Server 禁用扩展存储过程
  9. Markdown 常用语法
  10. Linux 常见命令示例【一】