LoginSignup
84
85

More than 5 years have passed since last update.

bowerと仲良くなる

Last updated at Posted at 2014-10-02

bowerを使っているのに素で

<script src="/bower_components/angular/angular.js"></script>

いちいちこういうコード書いてる人、いませんよね。bowerを使えるなら自動で挿入(インジェクション)すべきです。

main-bower-filesを活用すべし

しばらくgruntでgrunt-wiredepを使っていたんですが、useminに脳を焼かれたためGrunt自体やめました。Gulpでもwiredepのストリームを使うこともできますが、concatが辛めです。main-bower-filesを使いましょう。

実践

実際に動かしている構成に近づけようとしたら余計なものが結構入ってきてしまった感があるが、気にしない。

ちなみに本サンプルは
https://github.com/endaaman/main-bower-files-is-nice
に公開してあります。

サンプル構成
.
├── .bowerrc
├── bower.json
├── gulpfile.coffee
├── karma.conf.coffee
├── node_modules
│   └── [略]
├── package.json
├── public
│   └── bower_components
└── src
    ├── app.coffee
    ├── index.jade
    └── test
        └── app.coffee

Gulpで使う

index.jadeをindex.htmlにコンパイルして、開発時はbower_componentsから直接、プロダクションではconcatして、インジェクションしてみる。

サンプルでは、

bower.json
{
  "name": "example",
  "dependencies": {
    "angular": "~1.2.26",
    "angular-resource": "~1.2.26"
  },
  "devDependencies": {
    "angular-mocks": "~1.2.26"
  }
}

package.json
{
  "scripts": {
    "test": "./node_modules/karma/bin/karma start"
  },
  "devDependencies": {
    "coffee-script": "^1.8.0",
    "del": "^0.1.3",
    "gulp": "^3.8.8",
    "gulp-coffee": "^2.2.0",
    "gulp-concat": "^2.4.1",
    "gulp-inject": "^1.0.2",
    "gulp-jade": "^0.8.0",
    "karma": "^0.12.23",
    "karma-coffee-preprocessor": "^0.2.1",
    "karma-jasmine": "^0.1.5",
    "karma-phantomjs-launcher": "^0.1.4",
    "main-bower-files": "^2.0.0"
  }
}
index.jade
doctype html
html(ng-app="exampleApp")
    meta(charset="utf-8")
    body
        <!-- bower:js -->
        <!-- endinject -->
        <!-- inject:js -->
        <!-- endinject -->

という感じだとする。

gulpfile.coffee
g = require 'gulp'
jade = require 'gulp-jade'
inject = require 'gulp-inject'
concat = require 'gulp-concat'
coffee = require 'gulp-coffee'
del = require 'del'
bowerFiles = require 'main-bower-files'

conf =
    src: 'src'
    dest: 'public'
    prod: false
    bowerDir: 'public/bower_components'


g.task 'clean', ->
    del [
        "#{conf.dest}/**/*"
        "!#{conf.bowerDir}"
        "!#{conf.bowerDir}/**/*"
    ]

g.task 'coffee', ['clean'], ->
    g.src "#{conf.src}/*.coffee"
    .pipe coffee()
    .pipe g.dest "#{conf.dest}/"

g.task 'build:bower', ->
    if conf.prod
        g.src bowerFiles()
        .pipe concat('_vendor.js')
        .pipe g.dest("#{conf.dest}/")

g.task 'index', ['build:bower', 'coffee'], ->
    ignores = ['public/', 'client/']

    t = g.src "#{conf.src}/index.jade"
    .pipe jade pretty: not conf.prod
    if not conf.prod
        t.pipe inject(
            g.src(bowerFiles(),
                    base: conf.bowerDir
                    read: false),
                ignorePath: ignores
                name: 'bower'
        )
    t.pipe inject(
        g.src("#{conf.dest}/*.js", read: false),
            ignorePath: ignores
    )

    t.pipe g.dest "#{conf.dest}/"


g.task 'build', ['index']

g.task 'prod', ->
    conf.prod = true

g.task 'default', ['build']

venoder.jsだとapp.jsより後にインジェクションされてしまうため、本来なら順番をちゃんと指定するところだけど面倒だから、結合したファイルを_vendor.jsという名前にしている。

タスクは

  • gulp clean public/以下bower_components以外を掃除
  • gulp build(またはgulp) で開発用ビルド
  • gulp prod build でプロダクションビルド

になる。

gulp-injectの作者が「bowerに対してはmain-bower-filesを使うといいよ!」と言っているだけあって、楽ちんです。結合も楽勝。
Gulpでwiredepを使うとgulp-injectとは別でインジェクションされてしまい、少し気持ち悪いです。結合もやりにくい。

Karmaでも使える

というか、これが言いたくて書き始めた。

karma.conf.cofee
module.exports = (config) ->
    bowerFiles = require 'main-bower-files'

    files = [
        'src/**/*.coffee'
    ]
    files = bowerFiles(includeDev: true).concat files

    config.set
        basePath: ''
        frameworks: ['jasmine']
        files: files
        exclude: []
        preprocessors:
            'src/**/*.coffee': ['coffee']

        reporters: ['progress']
        port: 9876
        colors: true
        logLevel: config.LOG_INFO
        autoWatch: false
        browsers: ['PhantomJS']
        singleRun: true

includeDevを指定することでdevDependenciesも含めることができます。なので、KarmaのコンフィグにつかってもOKです。
これは使うべきです。というか、使わない手はありません。

src/app.coffee
'use strict'

angular.module 'exampleApp', [
    'ngResource'
]
.factory 'Add16', ->
    (i)->
        i + 16

.run (Add16)->
    console.log 'Add(3): ' + Add16(3)
    console.log 'Add(12): ' + Add16(12)
src/test/app.coffee
'use strict'

describe 'Add16', ->
    Add16 = null
    beforeEach ->
        module 'exampleApp'
        inject ($injector)->
            Add16 = $injector.get 'Add16'

    it ->
        expect(Add16(14)).toBe 30

angular-mocksがちゃんと含まれているので、テストも通ります。

CSSとかfontとかは守備範囲外

それでも個人的には問題になりません。というのも、CSSは生のCSSで使うことがほぼなく、大体LESSやSASS/SCSSで使うからです。この場合はインクルードパスをbowerにも通して、インポートやらで宣言を手元のCSSに引き込めばOKです。
fontは、minifyする必要がないのでbower_componentsをそのまま公開するか、公開しないならコピーしてもいいでしょう。そもそもfontsを扱うパッケージなどごく一部なので、苦にならないと思います。

84
85
2

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
84
85