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して、インジェクションしてみる。
サンプルでは、
{
"name": "example",
"dependencies": {
"angular": "~1.2.26",
"angular-resource": "~1.2.26"
},
"devDependencies": {
"angular-mocks": "~1.2.26"
}
}
{
"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"
}
}
doctype html
html(ng-app="exampleApp")
meta(charset="utf-8")
body
<!-- bower:js -->
<!-- endinject -->
<!-- inject:js -->
<!-- endinject -->
という感じだとする。
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でも使える
というか、これが言いたくて書き始めた。
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です。
これは使うべきです。というか、使わない手はありません。
'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)
'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を扱うパッケージなどごく一部なので、苦にならないと思います。