👌

Composerのバージョン指定。~を使うか^を使うか

2021/03/09に公開

この記事の目的

  • composer.jsonでのバージョン指定方法を根拠を持って決められるようになる。
  • 特に~と^の違いと利用方針を考える。

導入

PHPのパッケージ管理に多く使われるComposer
Composerはcomposer.jsonというファイルにインストールするパッケージとそのバージョンを保存し、それに応じて依存関係を解決してパッケージをインストールします。

バージョン指定にはいくつか記法があり、特定のバージョンを指定したり、あるいは範囲指定することもできます。
その範囲指定で使われるのが~(チルダ)と^(キャレット)です。(ex. ^1.2, ~2.3.2)
※ 他にも(dev-[branch name]でbranchを指定する方法や>=`で範囲を指定する方法などもありますが、この記事では触れません(詳しくはVersion and constraints - Composerを参照)。

両者の使い分けをどうすべきかなかなか決めきれなかったので調べてみた上での結論をまとめていきます。

~と^を用いた指定方式はセマンティックバージョニングを前提としたものなので、まずはセマンティックバージョニングについて簡単にまとめ、その後~と^を用いた指定方式を比較していきます。

セマンティックバージョニングについて

セマンティックバージョニングはMAJOR.MINOR.PATCHの形式でバージョンを管理するものであり、それぞれを上げる基準は以下のようになっています。
MAJOR: APIの非互換な変更
MINOR: 後方互換のある機能追加
PATCH: 後方互換のあるバグ修正
Semantic Versioning 2.0.0 | Semantic Versioning
※後方互換 = 以前のバージョンと同じ使い方で同じように動く

Composerでインストールできる公開packageをホスティングサービスであるPackagistではセマンティックバージョニングを強く推奨しています。
Packagist

The use of Semantic Versioning is strongly encouraged.

そのため、基本的に公開パッケージはセマンティックバージョニングに基づいてバージョンをタグづけしていることが多いです。

composer.jsonのおける~(チルダ)と^(キャレット)

composer.jsonのおける~と^によるバージョン指定はどのような意味を持つのか、セマンティックバージョニングを踏まえて見てみます。

~(チルダ)の場合

~は指定した最後の桁は上げてもいいという指定です。
Versions and constraints - Composer

指定 意味
~1.2 >= 1.2.0, < 2.0.0
~1.2.1 >= 1.2.1, < 1.3.0

セマンティックバージョニングに従っているpackageであれば、MINOR, PATCHは後方互換が保たれているはずなので、~1.2のように最小のMINORを指定するのがよくある使い方です。より慎重にしたい場合は ~1.2.1 のようにPATCHバージョンまであげるのを許容するという方法もとれます。

^(キャレット)の場合

^はセマンティックバージョニングの定義により忠実で、後方互換性を持つMINOR, PATCHのアップデートを許容する指定です。
Versions and constraints - Composer

指定 意味
^1.2 >= 1.2.0, < 2.0.0
^1.2.1 >= 1.2.1 < 2.0.0
^0.3 >= 0.3.0, < 0.4.0
※ 1.0.0未満は開発版と解釈され、PATCHのみしか上がらない

ライブラリを作っている場合は^で指定をすることで、できるだけ相互運用性(= その他のライブラリと相互に連携できるか)を高めることができます。

~と^の比較

~1.2^1.2 は結果的には全く同じです。
~1.2.1^1.2.1 はMINORまでのアップデートを許容するか、PATCHまでしか許容しないかという点で差があります。

どのように使い分けるか

ライブラリを利用する際に特定のパッチバージョン以降であれば、^1.2.1 、マイナーバージョン以降であれば ^1.2 or ~1.2 とするのが良いのではと考えています。
また、開発チーム内で慎重にアップデートしていく方針、あるいは対象ライブラリの開発がまだ安定していない場合は ~1.2.1 でパッチバージョンまでは許容するのが良いのではと思います。

ただし、セマンティックバージョニングはあくまで運用ルールであり、MINOR, PATCHバージョンが上がった際に後方互換性が必ず担保されるわけではないので無条件に信用していいわけではないです。
アップデートの際は利用するパッケージの変更点をチェックし(CHANGELOG.mdなど)、そのライブラリの利用箇所をテストはしましょう。

^1.2~1.2 の使い分けについては明確な基準が得られなかった(どちらも結果は変わらない)ので、何かあればぜひ教えていただきたいです。

リポジトリの特性による管理方針

^や~によるバージョン指定についてまとめてきましたが、最後にそもそもどんな場合に範囲指定を使うべきなのかという調べたなりの考えをまとめてみます。

再利用されないアプリケーション

Webアプリケーション本体など、他アプリケーションやライブラリからrequireされない場合。

  • PATCHまで指定する(ex. 2.3.2)
  • 固定バージョンで動作をアプリケーション側がちゃんとテストできるようにしておく

再利用されるライブラリ

他アプリケーションやライブラリからrequireされることを想定する場合。

  • ^や~を用い、利用側のバージョンを制限しすぎないようにする(相互運用性の確保)。

まとめ

Composerにおけるバージョン指定(主に~と^)について調べた結果をまとめてみました。
背景を知ることで使い方も自ずと見えてくるので、どう使い分けるべきか決めかねてる方のヒントになれば嬉しいです。

Discussion