在我的grunt插件中定义的运行任务:找不到任务

时间:2015-12-16 05:55:59

标签: gruntjs

我正在尝试执行一些我在Grunt文件中为项目编写的任务,并制作一个可重用的Grunt插件。我一直在努力找到一些文档来展示如何端到端地做这个,但是进展缓慢。简而言之,我的插件将采用HTML SWIG模板,并将其本地化为一堆不同的语言环境,由CSV文件指定。 (还有其他一些步骤,但我试图让这篇文章变得简单。)

我正在使用grunt v0.4.5,我使用了grunt-init并克隆了official Grunt docs中描述的grunt-plugin repo。这是我到目前为止所得到的:

grunt-emaillocalization/ (Plugin definition)
 - Gruntfile.js
 - package.json
 - tasks/
   - emaillocalization.js
   - bin/
     - convertCSVtoJSONForSWIG.js
     - makeEmailImages.js

这是插件定义Gruntfile.js。它使用了一个名为grunt-swig-localization的插件。为简洁起见简化:

'use strict';

module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    emaillocalization: {
      default_options: {
        options: {
          csvFile: 'config/emaillocalization/email.csv',
          templatesDir: 'config/emaillocalization'
        }
      }
    },

    swigLocalization: {
      main: {
        src: ['<%= emaillocalization.default_options.templatesDir %>/templates/*.swig', 'tmp/emaillocalization/json/*.json'],
        outputDir: 'dist/emaillocalization'
      }
    },

    /* Snip some other stuff */

  });

  // Actually load this plugin's task(s).
  grunt.loadTasks('tasks');

  // These plugins provide necessary tasks.
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-swig-localization');
  grunt.loadNpmTasks('grunt-shell');
  grunt.loadNpmTasks('grunt-text-replace');

};

这是插件定义tasks / emaillocalization.js任务定义,为简洁起见再次简化:

'use strict';

module.exports = function(grunt) {

  grunt.registerMultiTask('emaillocalization', 'Localizes email templates using a CSV as input.', function() {
    /* Snip setting some parameters */
    var taskList = ['emailprep', 'emailcsv2json', 'swigLocalization', 'copy:copyEmailImageFiles', 'shell:emailImages', 'replace:emailImageURLPrefix'];
    grunt.task.run(taskList);
  });

  /* Snip some other tasks */

};

如果我从插件定义repo运行 grunt emaillocalization ,它会执行它应该执行的所有操作;所有任务都得到处理。

包定义中的package.json文件包含以下内容,以强制swigLocalization插件与npm install捆绑在一起:

  "dependencies": {
    "grunt-swig-localization": "~0.1.0"
  },

现在在我的项目回购中,我在package.json中包含了我的grunt-emaillocalization插件:

  "devDependencies": {
    ...,
    "grunt-emaillocalization": "git@bitbucket.org:mycompany/grunt-emaillocalization.git"
  }

然后在项目的repo的Gruntfile.js中,我将它定义如下:

*global module:false*/
module.exports = function(grunt) {

  require("load-grunt-tasks")(grunt);
  require("time-grunt")(grunt);

  // Project configuration.
  grunt.initConfig({

    /* Snip a whole bunch of stuff */

    emaillocalization: {
      default_options: {
        options: {
          csvFile: 'email.csv',
          templatesDir: 'misc/emaillocalization'
        },
        files: {
          'tmp/default_options': ['test/fixtures/testing', 'test/fixtures/123']
        }
      }
    },

    gitinfo: {}

  });

  /* Snip a whole bunch of project registerTasks */

  grunt.loadTasks('tasks');
  grunt.loadNpmTasks('grunt-emaillocalization');

};

问题

我遇到的地方是,当我从项目仓库运行grunt emaillocalization.js 时(即我尝试使用我的插件),我得到了这个错误:

  

警告:找不到任务“swigLocalization”。使用--force继续。

调试

在我的插件来源中,如果我运行 grunt --help ,则swigLocalization会列为可用任务。

从我的项目中,我正在使用我的插件,如果我运行 npm list grunt-swig-localization插件(提供swigLocalization任务)肯定似乎可用:

├─┬ grunt-emaillocalization@0.1.0
│ └─┬ grunt-swig-localization@0.1.0
│   └─┬ swig@1.1.0
│     ├─┬ optimist@0.6.0
│     │ ├── minimist@0.0.10
│     │ └── wordwrap@0.0.3
│     └─┬ uglify-js@2.4.0
│       ├── async@0.2.10
│       ├─┬ optimist@0.3.7
│       │ └── wordwrap@0.0.3
│       ├─┬ source-map@0.1.43
│       │ └── amdefine@1.0.0
│       └── uglify-to-browserify@1.0.2

提前感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

经过多次修补,我找到了解决方案。

首先,当任务作为另一个项目中的插件运行时,将忽略插件定义中的Gruntfile.js。因此,必须在插件的任务文件中以程序方式设置任何捆绑插件的配置。这是我的简化工作任务/ emaillocalization.js:

'use strict';

module.exports = function(grunt) {
  var path = require('path');

  grunt.task.loadTasks(path.resolve(__dirname, '../node_modules/grunt-swig-localization/tasks'));

  grunt.registerMultiTask('emaillocalization', 'Localizes email templates using a CSV as input.', function() {
    /* Snip setting some parameters */
    var taskList = ['emailprep', 'emailcsv2json', 'generateHtmlFiles:'+this.options().templatesDir /* other tasks */];
    grunt.task.run(taskList);
  });

  grunt.registerTask('generateHtmlFiles', 'Create HTML files from JSON and template', function (src) {
    var templatePath = path.resolve(src) + path.sep + '*.swig';
    var jsonPath = path.resolve('tmp/emaillocalization/json') + path.sep + '*.json';
    // TIP: Don't resolve path for this.
    var outputPath = 'dist/emaillocalization';

    grunt.config.set('swigLocalization', {
      main: {
        src: [templatePath, jsonPath],
        outputDir: outputPath
      }
    });
    var taskList = ['emailprep', 'swigLocalization'];
    grunt.task.run(taskList);
  });

  /* Snip other tasks */
};

我在自己的插件中使用第三方任务的关键点是:

  1. 确保您的相关插件在package.json中设置为依赖项,而不是devDependencies。这可确保在您使用插件时运行npm install时安装它们。 (我已经这样做了。)
  2. 将插件的Gruntfile.js中的所有配置移动到插件的任务文件中,根据需要添加包装器任务,并在运行任务之前使用grunt.config.set()进行程序设置。你可以阅读
  3. 在使用grunt.task.loadTasks()之前,使用它们在您的任务文件中使用第三方插件显式加载任务。您还需要使用Node的path.resolve()和__dirname来引用插件的任务目录,相对于插件的任务文件。