注意! この記事はQiitaにて公開されていた内容をimportしたものです。
これらの内容は場合によっては陳腐化していて役に立たなくなっていたり、有害であったり、現在の著者の主張と異なることがあります。
皆様の判断の上でご利用いただけますと幸いです(度を超してヤバいものは著者に連絡して頂ければ対応します m(_ _)m)


はじめに

AngularJSを使ったフロントエンド開発をするうえで欠かせないのが、Yeomanを使ってテンプレートを作るやり方です。このとき、BowerGruntも一緒に導入されるのですが、これらツールが非常に便利なのでぜひ使いこなしたいところ。

さて、grunt-bower-installというプラグインが既に組み込まれています。これはBowerで取得したライブラリ類をHTMLファイルに 自動的に 挿入してくれるプラグインです。ある程度の依存関係も解決してくれます。Bowerで追加したライブラリを手動でHTMLファイルに書き込む必要がないので、うっかり書き漏れてライブラリが動かない、というミスが減ります。

grunt-bower-installの問題点

ただ、ちょっとした問題が発生します。それは、「Bowerで追加したライブラリが干渉することがある」ということ。

例えば以下の様なbower.jsonがあったとします。

{
  "dependencies": {
    "json3": "~3.2.6",
    "es5-shim": "~2.1.0",
    "angular": "~1.2.12",
    "angular-resource": "~1.2.12",
    "angular-cookies": "~1.2.12",
    "angular-sanitize": "~1.2.12",
    "angular-route": "~1.2.12",
    "angular-bootstrap": "~0.10.0",
    "angular-ui-router": "0.2.8-bowratic-tedium",
    "restangular": "~1.3.1", //  Lodash に依存している
    "angular-google-maps": "~1.0.9" //  Underscore.js に依存している
  }
}

このように定義されている状態でgrunt bower-installなどをすると、以下のようになります。(実際の結果と少し違うかもしれません。。。)

<!-- bower:js -->
<script src="bower_components/jquery/jquery.js"></script>
<script src="bower_components/momentjs/moment.js"></script>
<script src="bower_components/bootstrap/dist/js/bootstrap.js"></script>
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/angular-resource/angular-resource.js"></script>
<script src="bower_components/angular-cookies/angular-cookies.js"></script>
<script src="bower_components/angular-sanitize/angular-sanitize.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.js"></script>
<script src="bower_components/angular-ui-router/release/angular-ui-router.js"></script>
<script src="bower_components/lodash/dist/lodash.compat.js"></script>
<script src="bower_components/restangular/dist/restangular.js"></script>
<script src="bower_components/underscore/underscore.js"></script>
<script src="bower_components/angular-google-maps/dist/angular-google-maps.js"></script>
<!-- endbower -->

多くのライブラリと共に、lodash.compat.jsおよびunderscore.jsが依存解決されました。

ここで問題が発生します。UnderscoreもLodashも_を使用するのですが、依存解決されたときに両方ロードされておかしくなります。

LodashはUnderscoreよりももろもろ優れているらしいという情報をよく見かけるのと、そもそも同じ変数名を使っているライブラリがロードされているのが気持ち悪いので、Underscoreを挿入しないように設定します。

excludeオプションを指定する

Gruntfile.jsで以下のようにignoreを追加します。

// Automatically inject Bower components into the app
'bower-install': {
  app: {
    html: '<%= yeoman.app %>/index.html',
    ignorePath: '<%= yeoman.app %>/',
    exclude: [/underscore/]
  }
},

正規表現として定義しているのですが、もしかすると甘いかもしれないので適宜調整して頂ければ。

このようにexcludeオプションを定義すると、excludeにマッチしたものは自動挿入の対象から外れます。これでLodashとUnderscore.jsの干渉問題は解決されました!