トップ 最新 追記

2014-07-02 [長年日記]

_ 今さらComposer

ざっくりComposer

もう紹介記事は溢れているのでいちいち書く意味を感じないが、とりあえず。

  • PHP 5.3 以降で利用可能
  • package の依存管理ができる
  • Pear を含む複数の種類の package に対応している
  • Bundler のように project 単位での package の管理を支援してくれる(project 配下への download と autoloader)
  • Composer 独自の package 形式がある
  • packagist.org というデフォルトの repository がある(rubygems.org相当)

Composerという言葉の指す範囲

Bundler には Rubygems が package で Bundler が依存解決、という分かりやすい機能の対応関係があるが、Composer の場合は

  1. 依存解決を行う Composer
  2. Package を作る Composer

と、どっちも Composer が担っている。(Bundler もすでに bundle コマンドで gem が作れてしまうので、実装上は分離していても実際の利用上は分かりにくいのかもしれない。)

Composer のキモは composer.json だが、上に書いたような状態のため、Bundler と Rubygems の関係で言うところの Gemfile も .gemspec もどっちも composer.json に記述するという格好になってしまっている。

正直、この全部入りになってしまう感じが悪い意味で PHP っぽいなと感じる。また、JSON という汎用のフォーマットで書くようにしているのも混乱に拍車を掛けている気がする。パッと見でどっちの目的の composer.json なのか分からない。

Composerでinstallできるもの

上に書いた 2 の Package に相当する部分は間口が広く、

  • Pear
  • Pear2
  • Archive
  • VCS

に対応しているので、昔から使っている Pear Package があるのであれば、composer.json で repositories と require に書いてあげるだけでこれを install することができる。例えば Pear の HTTP であれば以下のような感じ。

{
  "repositories": [
    {
      "type": "pear",
      "url": "http://pear.php.net"
    }
  ],
  "require": {
    "pear-pear.php.net/HTTP": "*"
  }
}

これで composer install すると

vendor/pear-pear.php.net/HTTP/

以下に HTTP.php が入る。

当然だが Pear package を入れ始めると例によって Archive_Tar だの Structures_Graph だのも漏れなくついてくる。

PHP 5.3以降で新しく何かを作るならComposerを使うのが楽

基本的には Composer は Pear package などを使う方法を推奨しているわけではなく、packagist.org での composer package の公開を前提にしている。これはちょうど Ruby で言う rubygems.org のようなものだが、Bundler の Gemfile と違い、repositories に packagist.org を記述するという手間は必要なく、決め打ちで実行してくれる。

ただ、packagist.org に公開していなくても自作のコードを composer で install させることはできるので、以下にやったことを整理しておく。

Composer対応
  • composer.json を作って repository に入れるだけ
  • tag を正しく打っていればバージョンとして使われる(これは VCS 上の tag の話であって composer.json は関係ない)
  • 必要最低限は name だけでも ok(もちろん description などはあるべきだけど)
    • name は "vendor name/project name" の書き方で

cf. https://getcomposer.org/doc/04-schema.md#name

Composerでinstall
  • install する側の composer.json から composer 対応 repository を追加したうえで require してやる
  • 例えば手元の git repository なら url は local の filesystem になる

こんな感じ。

{
  "repositories": [
    {
      "type": "vcs",
      "url":  "/path/to/repository"
    }
  ],
  "require": {
    "vendor/project": "*"
  }
}

Bundler で言うところの

gem 'foo', :path => '/path/to/repository'

に似ているが、require の中で直接 repository の path を書くことはできない。

公開してよいものなら packagist に submit して install する側の composer.json を書き換えてやるとよい。

まっさらからのComposerまとめ

本当にまっさらの状態から自前で用意している依存コードを Composer で管理したい場合、

  • Composer 管理対象にしたい repository に composer.json を作って入れる
  • Composer で便利機能を install したい repository にも composer.json を置いて vendor 以下に依存コードを入れる

という二つの作業が必要。

過渡期の過ごし方

PHP 5.3 未満のコードにも 5.3 以上のコードにも対応する必要がある場合、当然だが Composer は万能薬にはならない。

この場合は

  • 依存されるライブラリなどの側のコードに composer.json を用意しつつ
  • PHP 5.3 未満の環境では Pear package や丸ごとコピーなどで対応する

必要がある。

例えば Pear package を利用して 5.1 環境に対応しつつ Composer で 5.3 以降の環境にも対応しようとする場合を考える。

まず Pear package で言うバージョンと Composer で言うバージョンを合わせるか合わせないかの判断が必要になってくる。もちろん合っている方が分かりやすいと思うが、Pear package が見ているバージョン情報はファイル名と package.xml 内のバージョン情報であり、Composer が見ているのはファイル名と VCS の tag である。これまで tag をちゃんと活用していない場合はここが一つネックとなる。

また metadata も別個に保持する必要がある。まぁ初回以降はそれほど大きな手間ではないが、package.xml と composer.json の両方に metadata を用意する必要がある。

やや煩雑だが、この手間を掛けておく価値はあると思う。既存の資産の Composer 対応は思った以上に簡単で、非公開のコード資産でも Composer 管理に移行してしまった方がいろいろ楽ができる。少なくとも VCS とうまく連携できるところはとてもイマドキで、Composer を知ったらいちいち package を作ったり channel サーバ立てたりしていた Pear 時代にはもう戻れないし、Composer が Pear package の install にも対応しているところは migration のためにとてもよい機能だと思う。

これでようやく手で zip や tarball 取って来て配置するという石器時代の手法にオサラバできるようになったんだな…。しみじみ。(自分の管理している範囲のお仕事のコードは自前で Pear package にして管理してたけど。これはこれで packaging と deploy が面倒だなと思っていたのであった。)

Tags: Composer PHP

2014-07-11 [長年日記]

_ Vagrant 1.2 + VirtualBox 4.2 -> Vagrant 1.5 + VirtualBox 4.3 へ移行した

準備

  1. 念のためすべての VM を shutdown する
  2. ~/.vagrant.d のバックアップを取っておく
  3. Vagrant, VirtualBox のバックアップを好みで取っておいてもよい(update は成功するけど、途中でどうしても緊急の作業をしたくなる可能性もあるかもしれない)

移行

  1. VirtualBox 4.3 の最新をインストール
  2. Vagrant 1.5 の最新をインストール(なんとなくstable指向)
  3. 適当な開発環境のところで vagrant plugin update (数分待つ)
  4. vagrant up
  5. VM は起動するが connection は lost する
  6. Ctrl + C で強制的に vagrant を終了してもう一度 vagrant up する と何事もなかったかのように使えるようになる
  7. 4 〜 6 をすべての VM でくり返す。すべての VM において 6 の挙動を示すが、根気よくつきあう
  8. 移行が終わったら .vagrant.d のバックアップは削除してよい

後始末

VirtualBox 上で VM がダブって見える場合があるので、GUI から消していく作業が必要になるかもしれない。

_ GenymotionからVMが起動しなくなってたので対処した

VirtualBox を上げた影響か、Genymotion から VM が起動しなくなってしまった。network connection が確立できなくて動かない。

  • NIC を削除しても復旧しない
  • VM を削除して入れ直しても復旧しない
  • hostonly アダプタを virtio-net から物理NICエミュレーションに切り替えると起動はするけどやっぱり通信できなくて終了する

結局、VirtualBox 上の vboxnet(hostonlyアダプタ)の DHCP サーバの設定を正しく行うことでなんとかなった。

この際は上に挙げた hostonly アダプタを virtio-net に戻しておく必要がある。


2014-07-19 [長年日記]

_ Sinatra AssetPackを試してみた

あるいは Kanazawa.rb meetup #23 に参加してきました。

何をしたかったか

  1. 現状では明らかに Rails に向いていないプロジェクトがある
  2. ホスティングはクラウドにしようと思うので、環境を先に決める必要がある
    • PHP でやるとか Ruby でやるとか
  3. 将来的には Rails で裏側をいじる必要あると思うんだけど、現状は表側だけで動けばいいし、Sinatra 使ってゴーじゃないか
  4. JS ヘビーになるし Sass も使いたいので Rails で言う Asset Pipeline 的なものは欲しい
  5. 「手間」は少なければ少ないほどよい

試した

  1. sprockets + sprockets-helpers
  2. sinatra-assetpack

Asset Pipeline が Sprockets を利用しているのは知っていたので Sprockets + Sprockets-Helpers がいちばん自分の既存の知識に近くて素朴な形になるんじゃないかと思って試してみたけど、結論から言うと自分の手には負えなかった。sprockets-helpers の提供する javascript_tag の展開するパスがどうしても思ったものにならない。 /assets/javascripts/application.js になってほしいのに /assets/application.js になったり /javascripts/javascripts/application.js になったり。中のコードをざっと眺めた感じでは正しく機能しそうに見えるんだけど。

実際に sprockets + sprockets-helpers でやってるというブログもいくつか見つけていたのだが、ダメだった。残念。

次に Sinatra AssetPack を試した。これは Rails の Asset Pipeline のようなものを Sprockets を利用せずに Sinatra 独自に実現するもの。後で気づいたけど、Sinatra のサイトで紹介されているのはこの方法なので、当然こっちの方がうまくいきやすそうである…。

Sinatra Recipes - Asset Management - Sinatra Assetpack

Sinatra AssetPack と Sprockets の比較

Sprockets は JavaScript ファイル、CSS ファイルの中に依存性を記述し、それを Sprockets が解決するという形なのだが、Sinatra AssetPack は Sinatra アプリ側に依存性を記述する。使い方としてはここがいちばん違う。書き方としてはこんな感じになる。

assets do
  serve '/assets/javascripts', from: 'assets/javascripts'

  js :app, '/javascripts/appication.js', [
    '/assets/javascripts/a.js',
    '/assets/javascripts/b.js'
  ]

  js_compression :jsmin
end

いろいろなJSライブラリを使いたいお

と思ったのならBowerを使うのがよさそう。

Bower

うーんイマドキ。

※ Rails には http://rails-assets.org/ という選択肢もあるけど、あれも結局 Bower 依存なので、Bower がいいんだろなという感じ。このように自分はすでに Rails で学んだ知識をもとにいろいろ類推して考える傾向にあるが、Rails にはいろいろな知が集まってくるので、この方法はとても効率がよいと考えている。Bower も名前は知っていてもピンと来ていなかったが、rails-assets のおかげで、ストンと理解できるようになった。

bower_components/ 以下の目的の JavaScript ファイルを上の依存ファイルの Array の中に納めてやればよい。

例えば jQuery 1.x を使いたかったら以下のような感じ。

bower.json

{
  "name": "myproj",
  "dependencies": {
    "jquery": "1.10"
  }
}

で、

bower install

これで試した時点で jQuery 1.10.2 が入る。

Sinatra AssetPack 側は以下のように bower_components も扱えるようにしてやる。

assets do
  serve '/assets/javascripts', from: 'assets/javascripts'
  serve '/bower_components',   from: 'bower_components'

  js :app, '/javascripts/appication.js', [
    '/assets/javascripts/a.js',
    '/assets/javascripts/b.js',
    '/bower_components/jquery/jquery.min.js'
  ]

  js_compression :jsmin
end

※ なんで 1.10 にしてあるかというと以下の production を試した時に 1.11 だとエラーになってしまうから。

Sinatra AssetPack でもう少し遊んでみて気づいたこと

  • rackup --env production で Asset Pipeline のように一つの JS にまとめてくれる
  • rake task も用意してあるので、いい具合に Rakefile に設定してやると rake assetpack:build が利用できる
  • rake assetpack:build すると coffee -> js 変換後のファイル、およびこれらを全部ひとまとめにした ファイルを生成してくれる
  • この生成済みのファイルがある場合はこれをそのまま serve してくれる
  • ない場合は動的に変換し、変換済みのコードをメモリにキャッシュして serve してくれる
  • jsmin は obsolete なので他のもの使った方がよいらしい

まとめ

とりあえずこれでフロントヘビーなプロジェクトでも手軽に PaaS に対応したサーバを用意しつつ、Rails の Asset Pipeline のように少ない手間で CoffeeScript や Sass などの恩恵に与ることができるようになった。よかった。

例えばこれが PaaS が node.js に対応しているならイマドキのフロントエンドっぽく全部 node.js で、bower + grunt + なんちゃらな感じで賄うこともできると思うんだけど、今回は Ruby か PHP というのが条件なので、Ruby を選択したうえでどうにかするという方針で調べた結果、Sinatra + Sinatra AssetPack という形になった。

結論 : 下手にググらずに本家ドキュメント読め。


2014-07-21 [長年日記]

_ Sinatraからrails-assets.orgを使う

先日

Sinatra AssetPackを試してみた - あーありがち(2014-07-19)

において Sinatra でも Asset Pipieline のようなことができてある程度満足していたのだが、Bower の部分は実は解決しておらず、もやもやしていた。

bower componentsをどうやってproduction環境にinstallするのか

具体的には deploy まで考えた際に bower components をどう扱うのがよりよい選択なのかが見えていなかった。恐らく解決方法は以下の二つのいずれかになると思う。

  1. bower_components も git repository に入れる
  2. deploy process の中で bower components の install を実行する

1 については実は Bower 界隈でも答えは出ていないっぽい。

この辺の扱いももやもやするが、単純な話、Ruby 向け PaaS を使う場合、そもそも

bower install

を自由に実行できるのだろうか。bundle install はもはや常識だろう。だが bower install はどうだ? そもそも node.js は入っているのか? npm は入っているのか?

これが 2 の部分の疑問である。2 が解決するなら 1 で悩む必要はない。(もちろん、deploy のタイミングで外部の repository が落ちていたらどうする?と言った問題は残るが)

そうするとやはり全部 gem で解決できる方が何かと面倒がない。最近は「そもそも gem でないものを gem で install できるようにするためだけに依存性の複雑さが増すのはよくないのではないか」という考えも増えてきているが、しかし現実には gem でないと自由に install できるかどうかは分からない。生サーバや IaaS なら自由だろうけど PaaS だとちょっとね。

rails-assets.orgはrailsじゃなくても使えるのでは?

https://rails-assets.org の存在は以前から知っていたし、前回の記事にも取り上げていたんだけど、名前から単純に Rails 専用だと思っていた。しかし、待てよ。

rails-assets.org が解決してくれるのは「bundler だけで bower components を install できるようにする」という部分だけで、実際に assets を探して読み込んでくれるのは Asset Pipeline の仕事なのでは?

ということで試したらできた。前回と同じ jQuery 1.10 を bower components として利用する場合は以下のように書くとよい。

Gemfile

(snip
source 'https://rails-assets.org'
(snip
gem 'rails-assets-jquery', '< 1.11'

Sinatraアプリ

assets do
  serve '/assets/javascripts', from: 'assets/javascripts'
  serve '/vendor/assets/jquery', from: 'vendor/ruby/2.0.0/gems/rails-assets-jquery-1.10.2/vendor/assets/javascripts/jquery'

  js :app, '/javascripts/appication.js', [
    'assets/javascripts/a.js',
    'assets/javascripts/b.js',
    'vendor/assets/jquery/jquery.js'
  ]

  js_compression :uglify
end

うおーだせぇ(笑)

要は Rails が自動で解決してくれる部分を手で書いただけ。

とは言えこれで

  • bundler が使えれば bower components を install することができ
  • 必要な assets を読み込むことができる

ということで、今度こそ見えている課題は全部クリアになったはず!

おまけ

jsmin は obsolete だし copyright も潰してしまうので、UglifyJS を使ってみた。いい具合だった。