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?'); 
  }
}

一、插件中使用插件

有時咱們須要在插件中使用插件來充分利用package資源, 可是因爲插件一般會再被其它package使用,tasksdir一般會定位到使用插件的package下的tasks; 因此就會報錯找不到相關packageName的tasks。javascript

那麼咱們能夠經過在插件中從新定義 loadNpmTasks 方法來實如今當前package下加載插件, 如:java

//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);
};

二、插件中文件的處理

能夠經過 grunt.file.setBase(cwd) 來設計,文件操做的cwdnode

三、任務名稱覆蓋問題

若是在插件中使用到一些很是經常使用的第三方插件, 如grunt-contrib-clean、grunt-contrib-copy等插件,有可能在使用插件的package中也會用到, 因此必定不要覆蓋使用插件的package的grunt配置,也不能merge配置, merge會致使執行順序的修改。異步

舉個例子:async

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,能夠改進以下:grunt

在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給同步過來。工具

四、task中的異步處理回調問題

若是在task的function body中存在異步調用,  這個問題和插件開發沒什麼關心,不過在用grunt寫工具時須要注意一下ui

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

那麼在grunt中是默認不會執行的, 緣由grunt的tasks 隊列運行機制, 隊列中的tasks運行完以後會執行exit, 退出當前進程;this

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以前執行, 如:spa

var done = this.async();
setTimeout(function() {
    //do something;
    done(true);
}, 2000);
相關文章
相關標籤/搜索