semver の使い方 — JavaScriptでセマンティックバージョニングを扱う定番パッケージ
一言でいうと
semver は、セマンティックバージョニング(SemVer)に準拠したバージョン文字列のパース・比較・範囲判定を行うためのライブラリです。npm 自身が内部で使用しているバージョン解析エンジンそのものであり、Node.jsエコシステムにおけるバージョン管理のデファクトスタンダードです。
どんな時に使う?
- 依存パッケージのバージョン互換性チェック — ユーザーの環境にインストールされたパッケージが、要求するバージョン範囲を満たしているか判定したい場合
- CI/CDパイプラインでのバージョン自動インクリメント — リリース時に
patch/minor/majorを自動で上げるスクリプトを組みたい場合 - バージョン文字列のバリデーション・正規化 — ユーザー入力や設定ファイルに含まれるバージョン文字列が正しい SemVer 形式かどうかを検証したい場合
インストール
# npm
npm install semver
# yarn
yarn add semver
# pnpm
pnpm add semver
TypeScript の型定義は本体に含まれていないため、別途インストールします。
npm install -D @types/semver
基本的な使い方
最もよく使うパターンは「バージョンの検証」と「範囲マッチング」です。
import semver from 'semver';
// バージョン文字列の検証
semver.valid('1.2.3'); // '1.2.3'
semver.valid('not-a-version'); // null
// 前後の空白や "v" プレフィックスを除去して正規化
semver.clean(' =v1.2.3 '); // '1.2.3'
// バージョンが指定範囲を満たすか判定
semver.satisfies('1.2.3', '>=1.0.0 <2.0.0'); // true
semver.satisfies('2.0.0', '>=1.0.0 <2.0.0'); // false
// バージョンの比較
semver.gt('2.0.0', '1.9.9'); // true
semver.lt('1.0.0', '1.0.1'); // true
semver.eq('1.2.3', '1.2.3'); // true
// バージョンのインクリメント
semver.inc('1.2.3', 'patch'); // '1.2.4'
semver.inc('1.2.3', 'minor'); // '1.3.0'
semver.inc('1.2.3', 'major'); // '2.0.0'
よく使うAPI — semver の主要メソッド解説
1. valid() / clean() — バージョン文字列の検証と正規化
import semver from 'semver';
// valid: 有効なら正規化された文字列を返し、無効なら null
semver.valid('1.2.3'); // '1.2.3'
semver.valid('v1.2.3'); // '1.2.3'
semver.valid('abc'); // null
// clean: 空白や先頭の "=" "v" を除去
semver.clean(' =v1.2.3 '); // '1.2.3'
semver.clean('invalid'); // null
2. satisfies() — 範囲マッチング
バージョンが指定した範囲(range)に含まれるかを判定します。npm の package.json で使われるレンジ構文をそのまま使えます。
import semver from 'semver';
// チルダ範囲: パッチレベルの変更を許容
semver.satisfies('1.2.4', '~1.2.3'); // true
semver.satisfies('1.3.0', '~1.2.3'); // false
// キャレット範囲: マイナーレベルの変更を許容
semver.satisfies('1.3.0', '^1.2.3'); // true
semver.satisfies('2.0.0', '^1.2.3'); // false
// OR 条件
semver.satisfies('3.0.0', '1.x || >=2.5.0 || 5.0.0 - 7.2.3'); // true
// プレリリースを含める場合
semver.satisfies('1.2.3-alpha.1', '>=1.2.3-alpha.0', {
includePrerelease: true,
}); // true
3. inc() — バージョンのインクリメント
リリース自動化で最も重宝するメソッドです。
import semver from 'semver';
semver.inc('1.2.3', 'patch'); // '1.2.4'
semver.inc('1.2.3', 'minor'); // '1.3.0'
semver.inc('1.2.3', 'major'); // '2.0.0'
// プレリリース付きインクリメント
semver.inc('1.2.3', 'prepatch'); // '1.2.4-0'
semver.inc('1.2.3', 'preminor', undefined, 'beta'); // '1.3.0-beta.0'
semver.inc('1.2.3', 'prerelease', undefined, 'alpha'); // '1.2.4-alpha.0'
// 既にプレリリースの場合
semver.inc('1.2.4-alpha.0', 'prerelease', undefined, 'alpha'); // '1.2.4-alpha.1'
4. sort() / rsort() / compare() — バージョンのソート・比較
import semver from 'semver';
const versions = ['3.0.0', '1.0.0', '2.1.0', '1.2.3', '2.0.0-alpha.1'];
// 昇順ソート
semver.sort(versions);
// ['2.0.0-alpha.1', '1.0.0', '1.2.3', '2.1.0', '3.0.0']
// ※ プレリリースは同じ major.minor.patch の通常版より前に来る
// 降順ソート
semver.rsort([...versions]);
// ['3.0.0', '2.1.0', '1.2.3', '1.0.0', '2.0.0-alpha.1']
// compare: Array.prototype.sort のコールバックとして使える
// -1, 0, 1 を返す
semver.compare('1.0.0', '2.0.0'); // -1
semver.compare('2.0.0', '1.0.0'); // 1
semver.compare('1.0.0', '1.0.0'); // 0
// diff: 2つのバージョン間の差分レベルを返す
semver.diff('1.0.0', '1.0.1'); // 'patch'
semver.diff('1.0.0', '1.1.0'); // 'minor'
semver.diff('1.0.0', '2.0.0'); // 'major'
semver.diff('1.0.0', '1.0.0'); // null
5. coerce() / maxSatisfying() / minVersion() — 実用ユーティリティ
import semver from 'semver';
// coerce: 不完全なバージョン文字列を SemVer に変換
semver.valid(semver.coerce('v2')); // '2.0.0'
semver.valid(semver.coerce('42.6.7.9.3-alpha')); // '42.6.7'
semver.valid(semver.coerce('not valid')); // null
// maxSatisfying: 範囲を満たすバージョンの中で最大のものを返す
const candidates = ['1.0.0', '1.2.3', '1.5.0', '2.0.0'];
semver.maxSatisfying(candidates, '^1.0.0'); // '1.5.0'
semver.maxSatisfying(candidates, '>=3.0.0'); // null
// minSatisfying: 範囲を満たすバージョンの中で最小のものを返す
semver.minSatisfying(candidates, '^1.0.0'); // '1.0.0'
// minVersion: 範囲を満たしうる理論上の最小バージョン
semver.minVersion('>=1.0.0')?.version; // '1.0.0'
semver.minVersion('^1.2.3')?.version; // '1.2.3'
semver.minVersion('~1.2.3')?.version; // '1.2.3'
// major / minor / patch: 各セグメントの数値を取得
semver.major('1.2.3'); // 1
semver.minor('1.2.3'); // 2
semver.patch('1.2.3'); // 3
semver.prerelease('1.2.3-alpha.1'); // ['alpha', 1]
類似パッケージとの比較
| パッケージ | 週間DL数 | 特徴 | 用途 |
|---|---|---|---|
| semver | 約3億+ | npm公式。フル機能の範囲マッチング対応 | バージョン管理全般 |
| compare-versions | 約200万 | 軽量(依存なし)。SemVer以外の形式にも対応 | 単純な比較のみで十分な場合 |
| semver-diff | 約50万 | semver のラッパー。2つのバージョン間の差分タイプを返す | diff のみ必要な場合 |
| node-semver | — | semver の旧名。同一パッケージ | — |
選定の指針: 範囲マッチング(^1.2.3 や ~1.0.0)が必要なら semver 一択です。単純な大小比較だけでバンドルサイズを極限まで削りたい場合は compare-versions が候補になります。
注意点・Tips
1. プレリリースの範囲マッチングに注意
デフォルトでは、プレリリースタグ付きバージョンは 同じ [major, minor, patch] タプルを持つ範囲 にしかマッチしません。
// 直感に反する挙動
semver.satisfies('3.4.5-alpha.9', '>1.2.3-alpha.3'); // false!
// 3.4.5-alpha.9 は数値的には大きいが、範囲の基準が 1.2.3 なのでマッチしない
// 通常版はマッチする
semver.satisfies('3.4.5', '>1.2.3-alpha.3'); // true
// プレリリースを常にマッチさせたい場合
semver.satisfies('3.4.5-alpha.9', '>1.2.3-alpha.3', {
includePrerelease: true,
}); // true
2. Tree-shaking / バンドルサイズの最適化
必要な関数だけを個別にインポートできます。バンドルサイズが気になるフロントエンドプロジェクトでは有効です。
// 全体をインポートする代わりに
import satisfies from 'semver/functions/satisfies';
import valid from 'semver/functions/valid';
satisfies('1.2.3', '^1.0.0'); // true
3. coerce() は万能ではない
coerce() は「それっぽい」文字列を SemVer に変換しますが、意図しない結果になることがあります。
semver.valid(semver.coerce('version 3 of the API')); // '3.0.0' — 文中の数字を拾ってしまう
ユーザー入力を受け付ける場合は、valid() で厳密に検証してから処理するのが安全です。
4. loose オプションは最終手段
{ loose: true } を渡すと、仕様に厳密でないバージョン文字列も受け入れます。外部システムとの連携でやむを得ない場合以外は使わないのがベストプラクティスです。
5. sort() は破壊的メソッド
semver.sort() は元の配列を 直接変更(in-place) します。元の配列を保持したい場合はスプレッド構文でコピーしてください。
const original = ['2.0.0', '1.0.0', '3.0.0'];
const sorted = semver.sort([...original]); // original は変更されない
まとめ
semver は npm エコシステムの根幹を支えるバージョン管理ライブラリであり、バージョン文字列の検証・比較・範囲マッチング・インクリメントといった操作を網羅的にカバーしています。CI/CD パイプラインの自動バージョニングから、プラグインシステムの互換性チェックまで、バージョンに関わるあらゆる場面で信頼して使える定番パッケージです。プレリリースの範囲マッチング挙動だけは直感に反しやすいので、includePrerelease オプションの存在を覚えておきましょう。