[Middleman 3] Middleman: Bower をつかってみる

なんとなく整理ができたので、リライトしてまとめておきます。
(2014/10/06)

% middleman version
Middleman 3.3.6

Bower

インストール

Bower がインストールされていなければ、下記でインストールします。

% npm install -g bower

npm も必要な場合は下記あたりで。

次にこのプロジェクトで Bower を使うよと init します。

bower.json というファイルが作成されます。

% bower init

いろいろ聞かれますが、利用するだけならすべてリターン&イエスで進めて大丈夫です。
bower.json まわりの内容は、こんな感じです。

.bowerrc を作成する

パッケージのインストールディレクトリと設定ファイルを定義しておきます。

{
  "directory": "bower_components",
  "json": "bower.json"
}

パッケージをインストールする

bower.json に設定を書き込んでくれる --save-dev オプションを付けて実行します。
Bootstrap 3Lightbox 2 をインストールしてみます。

% bower install --save-dev jquery
% bower install --save-dev bootstrap
% bower install --save-dev lightbox2

Bootstrap には、JavaScript, css, font が含まれます。
Lightbox には、JavaScript, css, img が含まれます。
どちらも jQuery が必要です。
bower_components というディレクトリに入ります。

Sprockets にパスを追加する

Middleman には、下記のパスが参照できるようになっています。

  • source/js
  • source/css
  • source/fonts
  • source/img
config.rb
config[:js_dir]     = 'js'
config[:css_dir]    = 'css'
config[:fonts_dir]  = 'fonts'
config[:images_dir] = 'img'

ここに展開されているファイルであれば、下記のような形で呼び出すことができるようになります。

//= require "foo.js"

bower_components 以下を呼び出せるように、Sprockets にパスを追加します。

config.rb
# Bower configuration
ready do
  sprockets.append_path "#{root}/bower_components"
end

それぞれ必要な CSS, JavaScript, Fonts, Images を呼び出していきます。

追記(2014/10/17)

sprockets.append_path をした状態で、asset gem の bootstrap-sass をあわせて利用したところ、build 時に LoadError が発生しました。
解決できず。

JavaScript

main.js に読み込みます。

main.js
//= require "jquery/dist/jquery.min.js"
//= require "bootstrap/dist/js/bootstrap.min.js"
//= require "lightbox2/js/lightbox.min.js"

CSS

同じ形式で main.scss に読み込みます。

main.scss
//= require "bootstrap/dist/css/bootstrap.min.css"
//= require "lightbox2/css/lightbox.css"

以下ダメな例。
SASS を利用しているので @import できるようにしたいのでこんなことをやってみました。

config.rb
  compass_config do |config|
    add_import_path = "/Users/****/projects/middleman-h5bp/bower_components/"
  end
main.scss
@import "bootstrap/dist/css/bootstrap.min.css";

これをコンパイルすると、いかん import となってしまいました。

main.css
@import url(bootstrap/dist/css/bootstrap.min.css);

Fonts

公式では

bower で管理されたアセットファイル – 画像, フォントなど – を Middleman プロジェクトの中で利用するには, sprockets.import_asset を使って bower 管理下のファイルをインポートする必要があります。

と書かれており、下記が例として載っています。
これを実行すると、js/jquery/dist/jquery.js が作成されますが、このままでは利用しづらいです。

sprockets.import_asset 'jquery/dist/jquery.js'

こちらで fonts もパスに追加してキレイに解決する方法が紹介されていました。
ありがとうございます。

.bowerrc の設定情報を元にインストールディレクトリ(今回は bower_components)を走査し、fonts ディレクトリを追加してくれています。

config.rb
# Bower configuration
ready do
  @bower_config = JSON.parse(IO.read("#{root}/.bowerrc"))
  Dir.glob(File.join("#{root}", @bower_config["directory"], "*", "fonts")) do |f|
    sprockets.append_path f
  end
  sprockets.append_path File.join "#{root}", @bower_config["directory"]
end

このように置き換えました。

middleman build でも /fonts へ関連ファイルが生成されていることが確認できました。

Images

おなじく img ディレクトリも処理したいです。
img や images も走査してくれるように変更しましたが、画像ファイルの場合は、パスの追加だけではファイル生成されませんでした。
middleman-sprockets の fixtures を確認したところでは、このような形で登録する必要がありそうです。

config.rb
sprockets.import_asset('lightbox2/img/close.png') { 'img/close.png' }

なお sprockets.append_path もあわせて行わないと、middleman server で表示されませんでした。

まとめ

というわけで bower install したコンポーネントへの対応をしました。
config.rb に無理矢理な感じで以下を追記しています。
すべての bower_components できちんと動くかは分かりませんが。。。

config.rb
# Bower configuration
def get_import_assets(path, split_str)
  array = []
  Dir.glob(["#{path}/*", "#{path}/.*"]).each do |name|
    unless File.directory?(name)
      a = name.split(File.join(split_str, '/'))
      array.push(a[1])
    end
  end
  array
end
ready do
  @bower_config = JSON.parse(IO.read("#{root}/.bowerrc"))
  bower_dir = @bower_config['directory']
  sprockets.append_path File.join("#{root}", bower_dir)
  Dir.glob(File.join("#{root}", bower_dir, '*', 'fonts')) do |path|
    sprockets.append_path path
  end
  dir_names = %w(img images)
  dir_names.each do |dir_name|
    Dir.glob(File.join("#{root}", bower_dir, '*', dir_name)) do |path|
      sprockets.append_path path
      get_import_assets(path, bower_dir).each do |image|
        sprockets.import_asset(image) { File.join(dir_name, '/', File.basename(image)) }
      end
    end
  end
end

スクリプトはともかく、このあたりを確認して Middleman を実戦で使えそうな気もしてきましたので、いろいろ試していきたいと思います。

補遺

bower_components は、別の方法を用いた方が良いのかな。

  • source/css, js, img, fonts へ手動でコピーする。
  • もしくは grunt で source/vendor あたりにレイアウトする。

.bowerrc で vendor/bower におくとスッキリする。

Rails では、CSS も画像もコピーされるよう。

また、Bowerによってvendor/assets/components以下にインストールされたJavaScriptライブラリに含まれるCSSファイルや画像ファイルは、ディレクトリ構成がそのままhttp://example.com/assets以下にコピーされます。

memo.