packagist内でlaravelの定義が巨大すぎて困る

Posted by Hiraku on 2016-06-05

ここでぼやいても誰にも伝わらない気がするけど、一旦吐き出しておきます。

事の経緯

私は https://packagist.org のミラーサイト packagist.jp を運営しています。 スクレイピングのプログラムがバグっていて、1ヶ月に一度ぐらい古くなったファイルを掃除して回る定期作業があるのですが、その中で妙にlaravel関連のパッケージ情報が巨大であることに気づきました。

例えば、私のMacのローカルキャッシュに残っているパッケージ情報をファイルサイズでsortすると、上位は全てlaravel関連のものになります。これらはpackagist.jpの中にミラーリングされているファイルと全く同じものです。

1971473 p-provider-2016-01.json
2058474 p-provider-2016-04.json
3687200 provider-illuminate$redis.json
3687241 provider-illuminate$hashing.json
3690806 provider-illuminate$encryption.json
3691771 provider-illuminate$http.json
3693165 provider-illuminate$translation.json
3693683 provider-illuminate$cookie.json
3694504 provider-illuminate$view.json
3694977 provider-illuminate$pagination.json
3701890 provider-illuminate$cache.json
3702948 provider-illuminate$mail.json
3703750 provider-illuminate$validation.json
3704972 provider-illuminate$session.json
3706146 provider-illuminate$auth.json
3712157 provider-illuminate$routing.json
3716228 provider-illuminate$exception.json
3720552 provider-illuminate$queue.json
3724346 provider-illuminate$database.json
3737402 provider-illuminate$container.json
3742829 provider-illuminate$config.json
3743325 provider-illuminate$log.json
3743507 provider-illuminate$events.json
3749134 provider-illuminate$console.json
3752406 provider-illuminate$filesystem.json
3758083 provider-illuminate$support.json

パッケージの情報だけで3.6MB? 確かに頻繁にアップデートを繰り返している人気のあるフレームワークですが、巨大すぎやしないでしょうか。

と思ってJSONの中身をみていくと、犯人がわかりました。

なんか、妙に関係ないパッケージの情報が含まれているのです。以下はilluminate/supportのjsonに含まれているパッケージ名だけを抜き取ったものですが、 laravel/frameworkilluminate/support 以外は「お前誰?」と言いたくなるような名前のパッケージばかりです。

ageras/framework
amaly/laravel-framework
chareice/framework
elfsundae/laravel-framework
icombats/laravel
illuminate/support
j42/framework
laravel/framework
legierski/laravel-framework-4.2-php7
litp/sae-laravel-framework
loduis/artisan
morrislaptop/laravel-five-package-bridges
noodlewitt/framework4.1fix
rewordpress/framework
rjacksonm1/laravel-framework-for-54
sweeney/framework
uofa/laravel-framework

これらのせいで、バージョン違いも含めて数えると、1250個もパッケージ情報が含まれていました。laravel自身は別に問題なくて、この無関係そうなパッケージ群が元凶のようです。

このクソみたいなパッケージを登録したのはどこのどいつだ

この現象、詳しい原因は追いかけきれてないのですが、おそらく、replaceの挙動によるものだと思います。

2014年ごろにこんな話が話題になっていました。replaceに関して少し記述があります。

まず、laravel関係のパッケージ構成についてなのですが、laravel/frameworkという巨大なパッケージが一つあり、これらをモジュールごとに分割したilluminate/ナントカというパッケージが複数存在しています。

laravel/frameworkにはパッケージ内容が全部含まれているので、これをインストールしさえすればilluminateナントカは個別にインストールする必要がありません。そこでreplace指定がされています。replaceは「このパッケージを置き換えるよ」という意味の指定で、それ自体は特に問題ないものだと思います。

https://packagist.org/packages/laravel/framework

しかし、laravelをforkして名前だけ変更し、誰かがそのfork版をpackagistに登録すると、このreplace指定は残り続けます。

つまり、こんなシナリオではないかと予想しています。

  1. 何者かがlaravel/frameworkをfork
    • 何か改変を加える
  2. そのfork版をrenameして、packagistに登録
  3. replace指定が残ったままのため、本家illuminate系にそのfork版の情報が含まれてしまった

受けている被害

パッケージ情報のjsonが肥大化すると、ちょっと困ったことになります。

まずcomposerはinstall / update時に、パッケージ情報を全てのバージョンだけ読み取ってメモリに載せ切ります。 そのため、laravel関係はインストール時に読み込むべき情報が巨大になり、composer update時に必要なメモリが多くなります。貧弱なメモリしか載せていないサーバーでは、laravelのupdateは不可能になっているはずです。

また、パッケージの更新時はこの3.6MBのjsonを毎度ダウンロードすることになるため、更新速度にも影響が出ます。複数ファイルが含まれているとファイルの更新頻度も高くなってキャッシュ効率が落ちます。

いいこと何にもないです。

私の主張

fork版をpackagistに登録するのやめろ

fork版とか、パッケージ名称が似たようなものをpackagistに登録しようとすると、それはやめて欲しいという警告が出てくるはずです。本家を改善するか、そもそも一人で使うだけならpackagistに登録するのではなくprivateパッケージとして運用すればいいだけです。

そもそも、replaceしなくていいのでは

laravelに関して言えば、replace機能ではなく、メタパッケージで十分なのではないかと思います。laravel/frameworkの中にはrequireでilluminate/ナントカが並んでいて、laravel/framework一個インストールすれば他は必要なくなる、みたいな感じ。

ただ、なんかpackagist自体の挙動が怪しいような気配もあるし、もう少し追っかけてみます。

PHPの最新記事