人気そうなGruntで、StylusとかCoffeeScriptをビルドする
Posted: Updated:
ナウいらしいからgruntいれてみるよ
GruntはJSで作られている、Rakeみたいなビルドタスクの管理ツールといえばよいのでしょうか。LESSやCoffee Scriptのようなコンパイルを必要するファイルの処理や、minify・concatなどもタスクとして実行できます。
デフォルトで、ファイル更新を監視するwatchタスクもあるため、コンパイル操作の自動化などにも使っていけます。npmでもgrunt関係のタスクが多数公開されているので、簡単にタスクを追加できます。
まずはnpmでgrunt本体をインストール。
# ng npm instlal grunt npm WARN prefer global grunt@0.3.11 should be installed with -g # ok npm install -g grunt
あ、グローバルじゃないとダメだった。よく読もう → 自分。-gでインストールした。
package.jsonの作成
gruntで簡単JSビルド - rh7's blogを参考に、ちゃんとpackage.json作る所から始める。
% npm init Package name: (grunt_test) GruntTest Description: grunt install test and try use. Package version: (0.0.0) Project homepage: (none) Project git repository: (none) Author name: ahomu Author email: (none) Author url: (none) http://havelog.ayumusato.com Main module/entry point: (none) Test command: (none) About to write to /Users/ayumusato/Desktop/grunt_test/package.json { "author": "ahomu (http://havelog.ayumusato.com)", "name": "GruntTest", "description": "grunt install test and try use.", "version": "0.0.0", "dependencies": {}, "devDependencies": {}, "optionalDependencies": {}, "engines": { "node": "*" } } Is this ok? (yes)
grunt.jsを初期化
initタスクで、grunt.jsを対話的に初期化できます。1度オレオレgruntできたらコマンド使わずに普通に使い回すような気もしつつ。
% grunt init:gruntfile Running "init:gruntfile" (init) task Please answer the following: [?] Is the DOM involved in ANY way? (Y/n) Y [?] Will files be concatenated or minified? (Y/n) Y [?] Will you have a package.json file? (Y/n) Y [?] Do you need to make any changes to the above before continuing? (y/N) N Writing grunt.js...OK Initialized from template "gruntfile". Done, without errors.
grunt.jsが初期化されました。"Is the DOM involved in ANY way?"の設問が、特に生成されるgrunt.jsに影響を及ぼしてなかった気がしつつ…。
タスクを入れてみる
Grunt: A JavaScript command line build tool | Public Draft | Just writing down what I've found and collectedを参考に、いくつかGrunt用のタスクをインストールします。
grunt-contribはかなり万能な感じ。上記の引用URLいわく、以下のタスクが入るらしい。CSSの圧縮・CoffeeScriptのコンパイル・Stylusのコンパイルをカバーしてくれたらとりあえず最低限はOK。あとはunderscoreのテンプレートをコンパイルってのが関数オブジェクトへの変換を指しているなら完璧?
- clean / ファイル、フォルダを削除
- coffee / CoffeeScriptをJavaScriptにコンパイル
- handlebars / handlebarsのテンプレートをコンパイル
- jade / jadeテンプレートをHTMLにコンパイル
- jst / underscoreのテンプレートをコンパイル
- less / lessファイルをCSSにコンパイル
- mincss / CSSを圧縮
- stylus / StylusファイルをCSSにコンパイル
- zip / ファイル、フォルダをzip圧縮 Grunt: A JavaScript command line build tool
% npm install grunt-contrib grunt-contrib@0.1.1 node_modules/grunt-contrib ├── zipstream@0.2.1 ├── underscore@1.3.3 ├── requirejs@2.0.4 ├── less@1.3.0 ├── stylus@0.27.2 (debug@0.7.0, cssom@0.2.4, mkdirp@0.3.3) ├── rimraf@2.0.2 (graceful-fs@1.1.8) ├── fstream@0.1.18 (inherits@1.0.0, graceful-fs@1.1.8, mkdirp@0.3.3) ├── tar@0.1.13 (inherits@1.0.0, block-stream@0.0.6) ├── jade@0.26.3 (commander@0.6.1, mkdirp@0.3.0) ├── handlebars@1.0.5beta (uglify-js@1.2.6, optimist@0.3.4) ├── clean-css@0.4.2 (optimist@0.3.4) └── yuidocjs@0.3.15 (graceful-fs@1.1.8, node-markdown@0.1.0, minimatch@0.1.5, express@2.5.11, yui@3.6.0pr3)
% npm install grunt-exec grunt-exec@0.1.1 node_modules/grunt-exec
task.registerTask
で独自定義のタスクも追加できるようだけど、なるべくベーシックなライブラリに由来するタスクは、さっさとこういうライブラリで入れてしまったほうがよさそう。
そいでgrunt.jsは今こんな感じ
最新ではなくて、このあと更に色々やっている最中なんですが、そのへんはまた次のエントリーとしてログを載せます。
/*global module:false*/ module.exports = function(grunt) { // Project configuration. grunt.initConfig({ pkg: '<json:package.json>', meta: { banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' + '<%= grunt.template.today("yyyy-mm-dd") %>\n' + '<%= pkg.homepage ? "* " + pkg.homepage + "\n" : "" %>' + '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author %>;' + ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */' }, concat: { dist: { src: ['<banner:meta.banner>', '<file_strip_banner:dist/js/main.js>'], dest: 'dist/js/main.js' } }, min: { dist: { src: ['<banner:meta.banner>', '<config:concat.dist.dest>'], dest: '<%= grunt.config("concat").dist.dest.replace(/js$/, "min.js") %>' } }, coffee: { app: { src : ['src/coffee/*.coffee'], dest : 'dist/js/main.js' }, test:{ src : ['test/spec_coffee/*.coffee'], dest: 'test/spec/main.js' } }, stylus: { app: { src : ['src/stylus/*.styl'], dest: 'dist/css/main.css' } }, watch: { coffee: { files: ['<config:coffee.app.src>', '<config:coffee.test.src>'], tasks: 'coffee' }, stylus: { files: ['<config:stylus.app.src>'], tasks: 'stylus' } } }); // Load grunt.loadNpmTasks('grunt-contrib'); // Default task.(から、lintとqunitを削除、あとでjasmine入れたい) // grunt.registerTask('default', 'lint qunit concat min'); grunt.registerTask('default', 'stylus coffee concat min'); };
npmで入れたgrunt-xxxxxなタスクは、grunt.loadNpmTasks
でロードできて、あとは普通にregsiterTaskでcoffeeとかstylusとかキーワードを指定でいます。(ここでのcoffee, stylusはgrant-contribに含まれるものを利用しています)
gruntを実行
実行はとりあえずgruntコマンドを実行するだけです。
# grunt default と同意 % grunt
これでdefaultタスク(上の例では、stylus, coffee, concat, minの順次実行)が実行されます。grunt task:args
のような感じで、特定のタスクのみ、そして引数として文字列を更に渡すことができるようです。
configのsrcとdest
coffeeタスクに対するconfigであれば、タスク名はcoffeeとして記述します。その中にサンプルのような構造でオブジェクトを指定することで、srcとdestのペアを複数指定できます。
srcがリソースファイル、coffeeならCoffeeScriptファイル(*.coffee)で、これは配列で複数指定できます。destは出力先のパスで、ここで指定したファイルにcoffeeのコンパイル結果が出力されます。
grunt.initConfig({ "タスク名": { "グループ名(なんでもいい)": { src : ['リソースファイルのパス', 'path/to/**/*.extention'], dest : 'path/to/dist.extension' }, "グループ名(なんでもいい)": { src : ['リソースファイルのパス', 'path/to/**/*.extention'], dest : 'path/to/dist.extension' } } }
grunt-contribのcoffeeに、前述のような指定をしたら、srcに該当しているファイルが全部コンパイル&結合されて、destのパスに渡されました。できれば結合させずに同名のJSファイルとして吐いてほしい…。
参考
- Meet Grunt: The Build Tool for JavaScript | Nettuts+
- gruntで快適JS/CSSビルド生活 - Takazudo hamalog
- Grunt: A JavaScript command line build tool | Public Draft | Just writing down what I've found and collected
- gruntで簡単JSビルド - rh7's blog
- 404 shin1のつぶやき ないわー Not Found: coffee, lessなプロジェクトをgruntで便利に
次回は、watch周辺と、独自タスク、grunt 0.4.0の利用あたりをログる予定。