zoukankan      html  css  js  c++  java
  • grunt 插件开发注意事项

    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);
  • 相关阅读:
    【POJ3237】Tree 树链剖分+线段树
    【BZOJ3531】[Sdoi2014]旅行 树链剖分+动态开点线段树
    【BZOJ4034】[HAOI2015]树上操作 树链剖分+线段树
    【BZOJ1984】月下“毛景树” 树链剖分+线段树
    【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
    【BZOJ1036】[ZJOI2008]树的统计Count 树链剖分
    树形DP水题杂记
    【BZOJ1827】[Usaco2010 Mar]gather 奶牛大集会 树形DP
    【BZOJ1864】[Zjoi2006]三色二叉树 树形DP
    【BZOJ1060】[ZJOI2007]时态同步 树形DP
  • 原文地址:https://www.cnblogs.com/mininice/p/3944857.html
Copyright © 2011-2022 走看看