48
47

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

grunt-pluginの作り方と解剖

Last updated at Posted at 2013-04-16

先日、はじめてgrunt-pluginを公開してみました。

そこでいくつか、「!?」となる箇所があったので、grunt-pluginをつくるときの注意まとめしてみます。
ある程度gruntを使っていて、Gruntfileもしこしこ書いたことある方向けです。

grunt-pluginとは?

そもそもgrunt-pluginとは何なんでしょうか。
最低限必要なのは、 gruntにtaskを追加するスクリプト 、ってとこだと思います。

例えば、こんなものでも、grunt-pluginと言えば言えそう。

var grunt = require('grunt');

grunt.registerTask('sample', 'sample task', function () {
    console.log('this is sample task!');
});

このgrunt.registerTaskというやつが、gruntにtaskを追加するメソッドです。
上の例の場合、sampleという名前の、"this is sample task!"と出力するだけのtaskができました。

これをGruntfileに混ぜ込んで書いておけば、ちゃんと↓のような感じで動くはず。

% grunt sample
this is sample task!


公式なgrunt-plugin

しかしせっかくなら、自分で作ったtaskを公開して、
他の人に使ってもらったりもしたくなるわけです。

オレオレなgrunt-pluginを、
grunt公式のplugin置き場(http://gruntjs.com/plugins) で公開するためには、
以下3つの条件を満たす必要があります。

  1. npmモジュールとして公開する (package.jsonがある)
  2. npmのpackage.jsonの中で、keywordsにgruntpluginを入れる
  3. registerTaskを呼ぶスクリプトは、tasksディレクトリ以下に置く

それでも案外シンプルですね!
また1と3を満たしていないと、grunt.loadNpmTasksで読み込むこともできません。

以下は、必要最低限なgrunt-plugin構成の例です。

ディレクトリ構成
grunt-sample
├── package.json
└── tasks
    └── sample.js
package.json
{
  "name": "grunt-sample",
  "version": "0.0.1",
  "description": "sample grunt plugin",
  "keywords": [
    "gruntplugin"
  ],
  "devDependencies": {
    "grunt": "~0.4.1"
  }
}
tasks/sample.js
module.exports = function (grunt) {
    grunt.registerTask('sample', 'sample task', function () {
        console.log('this is sample task!');
    });
};

あとは、このtasks以下のスクリプトの中で、
ごりごりやりたいことを書いていけば、pluginの完成です。

なお、npmモジュール公開までの手順は、このあとすぐ別記事にまとめるつもりです。

configのとりかた

Gruntfileを使って、様々な開発ツールのconfigをまとめて書けるのが、
gruntのすばらしいところの一つです。

Gruntfileがこんな感じだったら、

Gruntfile.js
var grant = require('grunt');

module.exports = function () {
    grunt.initConfig({
        sample: {
            hoge: 'hogehoge'
        }
    });  

    grunt.loadNpmTasks('grunt-sample');
};

このtask(simple)専用のconfigを参照したいときは、こんな感じ。

tasks/simple.js
module.exports = function (grunt) {
    grunt.registerTask('sample', 'sample task', function () {
        // configから"hoge"を取得
        var hoge = grunt.config('sample').hoge;

        console.log(hoge); // => 'hogehoge'
    });
};

このようにgruntオブジェクトからは、いろいろな情報がとれ、
jsonファイルを読み込むなどのUtilまでついてるので、
APIドキュメントを読んでいろいろ調べてみるといいと思います。

configを環境によって使い分ける

なお、grunt-compassやgrung-uglifyみたいに、
環境によってconfigを書き分けたい場合は、
grunt.registerTaskではなく**grunt.registerMultiTask**を使います。

こうすると、configのトップレベルのプロパティは、
その設定の環境名(target)とみなされます。

Gruntfile.js
var grant = require('grunt');

module.exports = function () {
    grunt.initConfig({
        sample: {
            dev: { // 開発環境
                hoge: 'hogehoge'
            },
            prod: { // 本番環境
                hoge: 'moge'
            }
        }
    });  

    grunt.loadNpmTask('grunt-sample');
};
tasks/simple.js
module.exports = function (grunt) {
    grunt.registerMultiTask('sample', 'sample task', function () {
        // 環境名の取得
        var target = this.target;

        // configから"hoge"を取得
        var hoge = grunt.config('sample')[target].hoge;
        console.log(hoge);
    });
};

この場合、gruntの実行結果は以下。

% grunt simple:dev
hogehoge
% grunt simple:prod
moge
% grunt simple
hogehoge
moge

環境名を付けずに実行すると、
すべての環境用の処理が一気に実行されてしまうので注意しましょう。

非同期taskを書くときは

ファイルを扱ったりして、非同期で進むtaskの場合、
そのまま書くと、taskの処理が終了する前にgrunt自体が終わってしまいます。

そういう場合には、asyncを使って、callbackの形にしましょう。

registerTaskに渡す関数の引数とかに、callback関数を入れても無駄なので、これまた注意です。

var fs = require('fs');

module.exports = function (grunt) {
    grunt.registerTask('sample', 'sample task', function () {
        // 環境名の取得
        var target = this.target;

        // 非同期タスクにする(doneにcallback関数が入る)
        var done = this.async();

        // configから"filename"を取得
        var filename = grunt.config('sample')[target].filename;

        fs.readFile(filename, 'utf8', function (err, data) {
            // ファイルをreadするのを待って、出力したら終了
            console.log(data);
            done();
        });
    });
};

まとめ

  • grunt-pluginのタスクは、tasks以下で書こう

  • registerTaskとregisterMultiTaskの違いは大事

  • 非同期処理の作り方がすこし特殊

  • 意味がわからなくなったら、コードを直接読むのがはやい

  • でもおおむね簡単。設定ファイル付きの開発ツールをいいかんじに公開できてすばらしい。

参考

48
47
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
48
47

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?