経緯

Bowerを使ってるとbower_componentsの中にjsのファイルが入っていきますが、jsだけでなく、README.mdやbower.jsonなどの余計なファイルもたくさんあって、あまり見やすいとは言えません。それが嫌で毛嫌いされているような感じがするBowerですが、ちゃんとそのあたり解決する術は残されています。

こんなときこそ、GruntJSです。GruntJSの導入はここでは触れませんので、インストールやらなんやらに関してはこちらの記事を参照。

前提

ディレクトリの構造は以下のようなものと仮定します。

bower_components/
┗ hoge
   ┣ bower.json (ライブラリのbower.json)
   ┗ hoge.js
vendors/
bower.json(プロジェクトのbower.json)
node_modules/
Gruntfile.js
package.json

注意すべきは、bower.jsonが二カ所にある点です。
これらを区別するためにライブラリのbower.json, プロジェクトのbower.jsonと呼ぶことにします。

ライブラリのbower.jsonはライブラリの依存関係を示すもので、プロジェクトのbower.jsonはプロジェクトにインストールしたライブラリを追記していくパッケージファイルです。

grunt-bower-taskのインストール

Gruntのタスクにgrunt-bower-taskというものがあります。こいつを使っていきたいので、なにはともあれ、インストールしてやりましょう。

grunt install grunt-bower-task --save-dev

Gruntfile.jsに記述

次にGruntfile.jsに以下のように追記していきます。

module.exports = function(grunt){
  grunt.initConfig({
    // bowerの設定
    bower: {
      install: {
        options: {
          targetDir: 'vendors', // vendorディレクトリ以下にファイルを入れていきます。
          layout: 'byType', // byComponentと選べるのですが、普通はbyTypeでいいと思います。
          install: true, // grunt実行時にbower:installを実行
          verbose: false, // ログの出力
          cleanTargetDir: true, // bower:installを実行したとき、targetDirを一度削除してからインストールしなおすか
          cleanBowerDir: false // bower:installを実行したときに、bower_componentsを消してインストールしなおすか
        }
      }
    }
  });

  // タスクの読み込み
  grunt.loadNpmTasks('grunt-bower-task');

  // タスクの登録
  grunt.registerTask('default', ['bower:install']);
};

これだけで、grunt bower:installとコマンドをうつと、Bowerでインストールされたファイルがvendor内に移動するようになります。jQueryなんかで試すといいかもしれません。

しかし困った

このタスクによって移動されるファイルはライブラリのbower.json内に記述されたmainで指定されたファイルです。
しかしながら、このmainが指定されていないライブラリも少なくありません。そしてmainが記述されていないものに対して、grunt bower:installを走らせると、README.mdなどを含めた全てのファイルが移動されてしまって、全くもって、問題の解決になりません。

これを解決するためにはドキュメントのbower.jsに設定を書いてやる必要があります。

bower.jsに必要ファイルの指定

ここではmainが書かれていないライブラリの代表例としてmodernizr.jsを使って、説明します。

bower_components/modernizr/bower.jsを見てみると、

{
  "name": "modernizr",
  "homepage": "https://github.com/Modernizr/Modernizr",
  "version": "2.8.3",
  "_release": "2.8.3",
  "_resolution": {
    "type": "version",
    "tag": "v2.8.3",
    "commit": "d6bb30c0f12ebb3ddd01e90b0bf435e1c34e6f11"
  },
  "_source": "git://github.com/Modernizr/Modernizr.git",
  "_target": "^2.6.2",
  "_originalSource": "modernizr"
}

と、mainが記述されていません。
これでは全てのファイルがvendorに入ってしまいます。

それを解決するためにプロジェクトのbower.jsonに設定を書いてやりましょう。

やり方は簡単で以下を追記してやればOKです。

"exportsOverride": {
  "modernizr": { // ライブラリ名
    "./": "modernizr.js"
  }
}

こうすることでvendors/modernizr/modernizr.jsだけを移動させることができます。

まとめ

ちょっと面倒くさいですが、これをしっかりやっておけば、管理がすごく楽になります。逆に、jsのライブラリを作ったときはbower.jsに忘れずにmainを書いてやらないと、自分が加害者になってしまいます。

一度設定すると、夢のように楽なフロントエンド開発が可能になるので、頑張りましょう。