Grunt for javascript libs
ナウでもヤングでもないけどGruntを使ったJS(ライブラリ|プラグイン)配布環境の構築メモ
scaffold的なテンプレを用意したほうが便利なんだけど、その前に基本的な構築とか
忙しい人はあとがきから読むことをおすすめする
やること
おおまかにはJSライブラリのテスト&ビルド用タスクの構築
- test
- jshint
- concat
- minify
document生成(今回はやめました)
これらを拙作のgithub.com/dameleon/tt.jsで整えてみる
ファイル構造などが分からなければ、上記リポジトリをcloneして、git checkout developされたし(masterに反映していないので)
package.json
package.jsonってなんぞや
ビルド環境や依存関係、バージョンなどのパッケージ情報を管理するファイル
用意しておけば、どこでも差異なく開発環境が作れる(はず)
気になる方はCommon.jsとかnpmのアレとか見てください。
see
- https://npmjs.org/doc/json.html
- http://wiki.commonjs.org/wiki/Packages/1.0
- http://publicdraft.studiomohawk.com/2012/12/16/npm-and-package.json/
package.jsonを作る
良いサンプルが見つからなかったのでとりあえずjQueryからパクる影響を受けましょう。
// package.json from jQuery
// https://github.com/jquery/jquery/blob/master/package.json
{
"name": "jquery",
"title": "jQuery",
"description": "JavaScript library for DOM operations",
"version": "2.0.0pre",
"homepage": "http://jquery.com",
"author": {
"name": "jQuery Foundation and other contributors",
"url": "https://github.com/jquery/jquery/blob/master/AUTHORS.txt"
},
"repository": {
"type": "git",
"url": "https://github.com/jquery/jquery.git"
},
"bugs": {
"url": "http://bugs.jquery.com"
},
"licenses": [
{
"type": "MIT",
"url": "https://github.com/jquery/jquery/blob/master/MIT-LICENSE.txt"
}
],
"dependencies": {},
"devDependencies": {
"grunt-compare-size": "0.3.1",
"grunt-git-authors": "1.0.0",
"grunt-update-submodules": "0.2.0",
"grunt-contrib-watch": "0.1.4",
"grunt-contrib-jshint": "0.1.1rc6",
"grunt-contrib-uglify": "0.1.1rc6",
"grunt": "0.4.0rc5",
"testswarm": "0.2.2"
},
"keywords":
}
// package.json for tt.js
{
"name": "tt.js",
"title": "jQuery",
"description": "JavaScript Library for fast DOM operations",
"version": "0.2.0",
"homepage": "",
"author": {
"name": "dameleon",
"url": "https://twitter.com/damele0n"
},
"repository": {
"type": "git",
"url": "https://github.com/dameleon/tt.js"
},
"bugs": {
"url": "https://github.com/dameleon/tt.js/issues"
},
"licenses": [
{
"type": "MIT",
}
],
"dependencies": {},
"devDependencies": {},
"keywords":
}
インスコ
Grunt本体のインスコ
// 本体をグローバルインストール(直接でもいいです)
$ npm install -g grunt
// projectのディレクトリで作業
$ cd path_to_project
// node_modulesをignore
$ echo node_modules >> .gitignore
// --save-dev付けておけば、package.json の devDependencies へ依存したパッケージとして書き込まれる
$ npm link grunt --save-dev
Gruntプラグインのインストール
今回の構成はこんな感じ
- linter : jshint > grunt-contrib-jshint
- test : buster.js > grunt-buster
- concat : grunt-contrib-concat
- minify : uglify > grunt-contrib-uglify
document : YUIDoc > grunt-contrib-yuidoc
この辺りは好みによって変更のこと。
Gruntプラグイン検索は本家で。
// 全部入れる
$ npm install grunt-contrib-jshint grunt-contrib-uglify grunt-contrib-concat grunt-contrib-yuidoc grunt-buster --save-dev
// buster.jsを使う場合、phantomjsのインストールが必要
$ brew install phantomjs
ここまでやると、package.json に以下の依存関係が書き込まれてるはず。
// @package.json
"devDependencies": {
"grunt": "~0.4.0",
"grunt-contrib-jshint": "~0.2.0",
"grunt-contrib-uglify": "~0.1.2",
"grunt-contrib-concat": "~0.1.3",
"grunt-contrib-yuidoc": "~0.4.0"
"grunt-buster": "~0.1.2",
}
setup grunt.js
環境は整ったので、grunt.jsの動作を設定していく
基本的な書き方はthe-gruntfileらへん
プラグインを入れた際の設定は各プラグインのnpmページ(ex.grunt-contrib-concat)を参考に
// projectのrootで(じゃなくてもいいけど)、gruntfile.jsを作って編集
// coffee scriptでも書けるので、お好きな方でどうぞ
$ vim gruntfile.js
// gruntfile.js
module.exports = function(grunt) {
grunt.initConfig({
// package.jsonを読み込む
// 以後の設定値で pkg.name のようにプロパティをテンプレート内で展開できる
pkg: grunt.file.readJSON('package.json'),
buster: {
test: {
// buster.jsのconfigファイルを指定
config: 'test/buster.js',
},
server: {
// port を指定(いらない?)
port: 1111
}
},
concat: {
options: {
// 既存の(既に書かれている)バナーを削除
stripBanners: true,
// 結合後のバナーのスタイルを指定
banner: '/** <%= pkg.title %> version:<%= pkg.version %> author:<%= pkg.author.name %> at:<%= grunt.template.today("yyyy-mm-dd") %> */\n'
},
dist: {
// ソースファイルの指定。ワイルドカードを用いず、1つずつでもOK
src: 'src/*.js',
// 結合後のファイル名を指定
dest: '<%= pkg.name %>.all.js'
}
},
uglify: {
options: {
// minify後のバナーのスタイルを指定
banner: '/** <%= pkg.title %> version:<%= pkg.version %> author:<%= pkg.author.name %> at:<%= grunt.template.today("yyyy-mm-dd") %> */\n'
},
build: {
// ソースファイルを指定
src: '<%= pkg.name %>.all.js',
// minify後のファイル名を指定
dest: '<%= pkg.name %>.min.js'
}
},
jshint: {
// ターゲットを指定
all: 'src/*.js',
// option を設定
options: {
curly: true,
eqnull: true,
eqeqeq: true,
undef: true,
validthis: true,
globals: {
tt: true
}
}
},
});
// pluginをロードする
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-buster');
// taskを登録
grunt.registerTask('test', ['jshint', 'buster']);
grunt.registerTask('default', ['jshint', 'buster', 'concat', 'uglify']);
};
run Grunt
必要なものは揃ったので、試しに走らせてみるテスト
// testのタスクを実行
$ grunt test
Running "jshint:all" (jshint) task
>> 1 file lint free.
Running "buster" task
buster-server running on http://localhost:1111
PhantomJS 1.8.1, Mac OS X: ...................................................
2 test cases, 51 tests, 164 assertions, 0 failures, 0 errors, 0 timeouts
Finished in 0.055s
Done, without errors.
// 何も指定していなければ default のタスクが実行される
$ grunt
Running "jshint:all" (jshint) task
>> 1 file lint free.
Running "buster" task
buster-server running on http://localhost:1111
PhantomJS 1.8.1, Mac OS X: ...................................................
2 test cases, 51 tests, 164 assertions, 0 failures, 0 errors, 0 timeouts
Finished in 0.062s
Running "concat:dist" (concat) task
File "tt.all.js" created.
Running "uglify:build" (uglify) task
File "tt.min.js" created.
Uncompressed size: 27308 bytes.
Compressed size: 2293 bytes gzipped (10683 bytes minified).
Done, without errors.
出力としてエラーを受け取った場合は、その箇所を修正して再度実行
結果、ファイル出力として、今回の設定では2つのファイルが生成される
- tt.all.js
- tt.min.js
また、concatとuglifyともにバナーを設定したので、それも確認する(今回はどっちも一緒[それもどうかと思うが])
// @tt.all.js#1
/** tt.js version:0.2.0 author:kei takahashi(twitter@dameleon) at:2013-03-05 */
// @tt.min.js#1
/** tt.js version:0.2.0 author:kei takahashi(twitter@dameleon) at:2013-03-05 */
以上で、簡単なビルド環境の設定は終了
あとは複数人でも一人で複数環境でも、安心して開発を行える(はず)
あとがき
実はgrunt-initなる機能があって、既に用意されたテンプレみたいなのも展開できたりもする
手っ取り早くGruntを利用したければこちらのほうがいいかも(ある程度の編集は必要)
see: Project Scaffolding
$ npm install -g grunt-init
// 試しにcommonjsのテンプレをcloneして
$ git clone [email protected]:gruntjs/grunt-init-commonjs.git ~/.grunt-init/commonjs
// 走らせてみる
$ grunt-init commonjs
// 対話式でいろいろ聞かれる
Please answer the following:
[?] Project name (grunttest) hoge
[?] Description (The best project ever.) fuga
[?] Version (0.1.0) 0.1.0
[?] Project git repository (git://github.com/dameleon/grunttest.git)
[?] Project homepage (https://github.com/dameleon/grunttest)
[?] Project issues tracker (https://github.com/dameleon/grunttest/issues)
[?] Licenses (MIT)
[?] Author name (dameleon)
[?] Author email ()
[?] Author url (none)
[?] What versions of node does it run on? (>= 0.6.0)
[?] Main module/entry point (lib/hoge)
[?] Npm test command (grunt nodeunit)
[?] Do you need to make any changes to the above before continuing? (y/N)
// なんか色々作ってくれる
$ ls
.gitignore
.jshintrc
Gruntfile.js
LICENSE-MIT
README.md
lib
package.json
test
もちろん、テンプレートを自分で作ることもできる
see: Project Scaffolding#custom-templates
今度は、今回作ったGrunt周りのものをオレオレテンプレ化してみたりとか
その前にはてブロを綺麗にしないと見づらくてしょうがない…