CLOVER🍀

That was when it all began.

npm installなどで使うバージョンがよくわからなかったので、調べてみました

これは、なにをしたくて書いたもの?

npm install(npm i)でモジュールをインストールする時にバージョンを指定したり、package.jsonに記載される
バージョン表記について雰囲気でしか見ていなかったので、ちゃんと見てみようかなと。

なお、パッケージの依存関係やより新しいバージョンがリリースされているかどうかの確認には、こちらを。

npmでプロジェクトの依存関係の確認や、依存パッケージのバージョン確認などを行ってみる - CLOVER🍀

どういうところが気になっていた?

^や~でバージョンの範囲を絞り込んでいるのはまだいいのですが、よくわかっていなかったのはこういうものですね。

v[Major Version]を指定したり

$ npm install redis@v3

nextが指定されたりするもの、などですね。

$ npm install react-router@next

ドキュメントを見つつ、実際にコマンドを使って確認していきましょう。

環境

今回の環境は、こちら。

$ npm --version
8.1.2

ドキュメントを参照する際にバージョンが必要な場合は、v8のものを見ていきます。

パッケージとモジュールについて

まずは、パッケージとモジュールについて。ドキュメントはこちら。

About packages and modules | npm Docs

両者は、厳密には違うものなんですね。

「パッケージ」とは、package.jsonによって記述されたファイルやディレクトリのことを指しています。

About packages and modules / About packages

一方で「モジュール」というのは、node_modulesディレクトリ内にある任意のファイルやディレクトリで、
Node.jsのrequire関数でロードできるものです。

About packages and modules / About modules

npmでインストールするのは「パッケージ」になり、実際にプログラムで利用できる状態のものは「モジュール」と呼ぶ、
といったところでしょうか。

パッケージのフォーマットは、以下のいずれかになります。

  • (a) package.jsonで記述されたプログラムを含むディレクトリ
  • (b) (a)をgzipしたtarball
  • (c) (b)を解決できるURL
  • (d) (c)をレジストリーで<name>@<version>として公開したもの
  • (e) (d)を<name>@<tag>で指したもの
  • (f) (e)を満たすlatestタグを持つ<name>(パッケージ名)
  • (g) git cloneした時に(a)になるもの

About packages and modules / About package formats

ふだん何気なくやっている以下のコマンド(バージョン指定なし)は、(f)を使っていることになりますね。

$ npm install [パッケージ名]

やや一足飛び感がありますが、それは後ほど…。

スコープ

パッケージには、スコープを持たせることができます。

About scopes | npm Docs

スコープとは、npmにサインアップするか、Organizationを作成すると付与されるもので、ユーザーまたはOrganizationが
単位になります。

スコープを使うことで、同名のパッケージの競合を防ぐことができます、と。

書式は以下です。

@[スコープ名]/[パッケージ名]

例にも書かれていますが、たとえばnpmスコープであれば以下になります。

@npm/package-name

スコープはパブリックパッケージであれば、使っても使わなくてもよいみたいです。

About public packages | npm Docs

プライベートパッケージの場合は、常にスコープを使うことになります。

About private packages | npm Docs

たまに、npm installする時に@がついているパッケージの意味がわかりました…。

パッケージのバージョンついて

パッケージのフォーマットで出てきた、<version>と<tag>について見ていきましょう。

About semantic versioning | npm Docs

Adding dist-tags to packages | npm Docs

まずはバージョンから。npmパッケージは、セマンティックバージョニングに習うことが推奨されています。

About semantic versioning | npm Docs

Semantic Versioning 2.0.0 | Semantic Versioning

セマンティックバージョニングは、メジャー、マイナー、パッチの3つのバージョンを表す数字で構成されるわけですが、
npmではパッケージの更新範囲を指定できます。

ドキュメントに習って1.0.4を例にすると、こんな感じになります。

  • パッチリリースの更新範囲に留めたい場合 … 1.0、1.0.x、~1.0.4
  • マイナーリリースの更新範囲に留めたい場合 … 1、1.x、^1.0.4
  • メジャーリリース(要するに最新) … *、x

たとえば、なにも考えずにExpressをインストールすると

$ npm i express

現時点では以下のような表記になりますが、これはExpress 4.17.2より新しい4.x系で更新範囲を指定していることに
なります。

  "dependencies": {
    "express": "^4.17.2"
  }

実際に使いたいパッケージと、選択されるバージョンの範囲を確認したい場合は、以下のサイトを使うとよいでしょう。

npm semantic version calculator

指定したパッケージのバージョンが一覧表示され、指定したバージョンパターンにマッチするバージョンがハイライト
されるので、記述方法の確認になります。

"v"について

たまに、npm install時にバージョンにvを付けて指定している例を見ることがあります。

これはどう捉えたらよいのでしょうか?

npmのドキュメントには特に記述がなさそうですが、セマンティックバージョニングの方を見るとなんとなく
わかりそうです。

Semantic Versioning 2.0.0 / Is “v1.2.3” a semantic version?

たとえば、v1.2.3はセマンティックバージョニングではありません。ただ、セマンティックバージョニングの前に
vを付けることはバージョン番号を示す一般的な方法となっています。
v1.2.3はタグで、1.2.3がセマンティックバージョンニングとなります。

となると、以下のような例はvを読み飛ばせば良さそうですね(メジャーバージョン3.xの範囲でパッケージを
インストールする)。

$ npm install redis@v3

なんとなく意味はわかるのですが、情報を追うとこんなところでしょうか。

パッケージのタグについて

続いて、タグについて。

Adding dist-tags to packages | npm Docs

タグはセマンティックバージョンに対して、人間が読める形式のラベルを付与したものです。

ところで、このドキュメントにはlatestなどについては書かれていません。それは、npm dist-tagコマンドの
ドキュメントに書かれています。

npm-dist-tag | npm Docs

latestタグ、nextタグ

タグについて、もう少し追ってみます。

npm dist-tagコマンドのドキュメントを見ると、latestとnextに関する内容がもう少し書いてあります。

npm-dist-tag / Description

latestタグは、パッケージを公開する時に--tagオプションが使われていない限り、そのバージョンがlatestタグとして
設定されます。

Publishing a package sets the latest tag to the published version unless the --tag option is used.

そして、パッケージをインストールする際に@<version>または@<tag>を指定していない場合、デフォルトで
latestタグのパッケージをインストールする振る舞いをします。

By default, npm install (without any @ or @ specifier) installs the latest tag.

By default, the latest tag is used by npm to identify the current version of a package, and npm install (without any @ or @ specifier) installs the latest tag.

npm-dist-tag / Purpose

これが、npm installでパッケージ名のみを指定した場合に(f)(latestタグ)が指定されたことと同じになる、
という理由ですね。

通常、latestは安定したリリースバージョンにのみ使用し、リリース前の安定していないバージョンなどには
他のタグを使用します。

Typically, projects only use the latest tag for stable release versions, and use other tags for unstable versions such as prereleases.

latestを除いて、npmには特別な意味を持つタグはありません。

Other than latest, no tag has any special significance to npm itself.

nextタグについては、次のバージョンを識別するために一部のプロジェクトが使用していることがある、といった
位置づけ(慣例?)みたいですね。

The next tag is used by some projects to identify the upcoming version.

他の例としては、stable、beta、dev、canaryなどが挙げられるようです。

For example, a project might choose to have multiple streams of development and use a different tag for each stream, e.g., stable, beta, dev, canary.

ここまでで、およそバージョンとタグはわかった気がします。

npm view

ここから先は、少しnpmコマンドを見ていきましょう。

まずはnpm viewから。

npm-view | npm Docs

viewの代わりに、エイリアスとしてinfo、show、vが利用できます。

Expressで試してみましょう。

$ npm view express

express@4.17.2 | MIT | deps: 30 | versions: 265
Fast, unopinionated, minimalist web framework
http://expressjs.com/

keywords: express, framework, sinatra, web, http, rest, restful, router, app, api

dist
.tarball: https://registry.npmjs.org/express/-/express-4.17.2.tgz
.shasum: c18369f265297319beed4e5558753cc8c1364cb3
.integrity: sha512-oxlxJxcQlYwqPWKVJJtvQiwHgosH/LrLSPA+H4UxpyvSS6jC5aH+5MoHFM+KABgTOt0APue4w66Ha8jCUo9QGg==
.unpackedSize: 209.6 kB

dependencies:
accepts: ~1.3.7            content-type: ~1.0.4       depd: ~1.1.2               finalhandler: ~1.1.2       on-finished: ~2.3.0        qs: 6.9.6                  
array-flatten: 1.1.1       cookie-signature: 1.0.6    encodeurl: ~1.0.2          fresh: 0.5.2               parseurl: ~1.3.3           range-parser: ~1.2.1       
body-parser: 1.19.1        cookie: 0.4.1              escape-html: ~1.0.3        merge-descriptors: 1.0.1   path-to-regexp: 0.1.7      safe-buffer: 5.2.1         
content-disposition: 0.5.4 debug: 2.6.9               etag: ~1.8.1               methods: ~1.1.2            proxy-addr: ~2.0.7         send: 0.17.2               
(...and 6 more.)

maintainers:
- mikeal <mikeal.rogers@gmail.com>
- dougwilson <doug@somethingdoug.com>
- jasnell <jasnell@gmail.com>

dist-tags:
latest: 4.17.2       next: 5.0.0-alpha.8  

published 2 weeks ago by dougwilson <doug@somethingdoug.com>

パッケージの情報が表示されます。

latestタグは4.17.2、nextタグも設定されていて5.0.0-alpha.8であることがわかります。

この記述は、以下と同義です。

$ npm view express@latest

nextタグを使用すると、開発中の5系の情報が表示されます。

$ npm view express@next

express@5.0.0-alpha.8 | MIT | deps: 31 | versions: 265
Fast, unopinionated, minimalist web framework
http://expressjs.com/

〜省略〜

パッケージにどんなバージョンがあるかは、npm view [パッケージ名] versionsで確認することができます。

$ npm view express versions
[
  '0.14.0',        '0.14.1',        '1.0.0-beta',    '1.0.0-beta2',
  '1.0.0-rc',      '1.0.0-rc2',     '1.0.0-rc3',     '1.0.0-rc4',
  '1.0.0',         '1.0.1',         '1.0.2',         '1.0.3',
  '1.0.4',         '1.0.5',         '1.0.6',         '1.0.7',
  '1.0.8',         '2.0.0-beta',    '2.0.0-beta2',   '2.0.0-beta3',
  '2.0.0-rc',      '2.0.0-rc2',     '2.0.0-rc3',     '2.0.0',
  '2.1.0',         '2.1.1',         '2.2.0',         '2.2.1',

  〜省略〜

  '4.8.7',         '4.8.8',         '4.9.0',         '4.9.1',
  '4.9.2',         '4.9.3',         '4.9.4',         '4.9.5',
  '4.9.6',         '4.9.7',         '4.9.8',         '4.10.0',
  '4.10.1',        '4.10.2',        '4.10.3',        '4.10.4',
  '4.10.5',        '4.10.6',        '4.10.7',        '4.10.8',
  '4.11.0',        '4.11.1',        '4.11.2',        '4.12.0',
  '4.12.1',        '4.12.2',        '4.12.3',        '4.12.4',
  '4.13.0',        '4.13.1',        '4.13.2',        '4.13.3',
  '4.13.4',        '4.14.0',        '4.14.1',        '4.15.0',
  '4.15.1',        '4.15.2',        '4.15.3',        '4.15.4',
  '4.15.5',        '4.16.0',        '4.16.1',        '4.16.2',
  '4.16.3',        '4.16.4',        '4.17.0',        '4.17.1',
  '4.17.2',        '5.0.0-alpha.1', '5.0.0-alpha.2', '5.0.0-alpha.3',
  '5.0.0-alpha.4', '5.0.0-alpha.5', '5.0.0-alpha.6', '5.0.0-alpha.7',
  '5.0.0-alpha.8'
]

また、バージョンの範囲表記と組み合わせることで、こちらのサイトと近い確認も行えます。

https://semver.npmjs.com/

いくつか、確認してみましょう。バージョンまたはバージョンの範囲を指定する場合、npm view [パッケージ名] version
となることに注意です(versionsではなく、version)。

$ npm view express@4 version                                                                                         
express@4.0.0 '4.0.0'                                                                                                                                                             
express@4.1.0 '4.1.0'                                                                                                                                                             
express@4.1.1 '4.1.1'                                                                                                                                                             
express@4.1.2 '4.1.2'                                                                                                                                                             
express@4.2.0 '4.2.0'                                                                                                                                                             
express@4.3.0 '4.3.0'                                                                                                                                                             
express@4.3.1 '4.3.1'                                                                                                                                                             
express@4.3.2 '4.3.2'                                                                                                                                                             
express@4.4.0 '4.4.0'                                                                                                                                                             
express@4.4.1 '4.4.1'                                                                                                                                                             
express@4.4.2 '4.4.2'                                                                                                                                                             
express@4.4.3 '4.4.3'                                                                                                                                                             
express@4.4.4 '4.4.4'

〜省略〜

express@4.15.0 '4.15.0'
express@4.15.1 '4.15.1'
express@4.15.2 '4.15.2'
express@4.15.3 '4.15.3'
express@4.15.4 '4.15.4'
express@4.15.5 '4.15.5'
express@4.16.0 '4.16.0'
express@4.16.1 '4.16.1'
express@4.16.2 '4.16.2'
express@4.16.3 '4.16.3'
express@4.16.4 '4.16.4'
express@4.17.0 '4.17.0'
express@4.17.1 '4.17.1'

こちらでも同じ結果になります。

$ npm view express@v4 version

パッチバージョンの範囲指定。

$ npm view express@~4.15.0 version
express@4.15.0 '4.15.0'
express@4.15.1 '4.15.1'
express@4.15.2 '4.15.2'
express@4.15.3 '4.15.3'
express@4.15.4 '4.15.4'
express@4.15.5 '4.15.5'

マイナーバージョンの範囲指定。

$ npm view express@^4.15.0 version
express@4.15.0 '4.15.0'
express@4.15.1 '4.15.1'
express@4.15.2 '4.15.2'
express@4.15.3 '4.15.3'
express@4.15.4 '4.15.4'
express@4.15.5 '4.15.5'
express@4.16.0 '4.16.0'
express@4.16.1 '4.16.1'
express@4.16.2 '4.16.2'
express@4.16.3 '4.16.3'
express@4.16.4 '4.16.4'
express@4.17.0 '4.17.0'
express@4.17.1 '4.17.1'
express@4.17.2 '4.17.2'

ピンポイントでも指定できます。

$ npm view express@4.17.1 version
4.17.1


$ npm view express version
4.17.2


$ npm view express@latest version
4.17.2


$ npm view express@next version
5.0.0-alpha.8

最後に、蛇足的にnpm searchも書いておきます。

npm-search | npm Docs

npm searchを使うことで、パッケージの検索ができます。

こちらでの検索と同じですね。

npm

expressでの確認例。

$ npm search express
NAME                      | DESCRIPTION          | AUTHOR          | DATE       | VERSION  | KEYWORDS                                                      
express                   | Fast,…               | =mikeal…        | 2021-12-17 | 4.17.2   | express framework sinatra web http rest restful router app api
cors                      | Node.js CORS…        | =dougwilson…    | 2018-11-04 | 2.8.5    | cors express connect middleware
express-jwt               | JWT authentication…  | =woloski…       | 2021-08-11 | 6.1.0    | auth authn authentication authz authorization http jwt token oauth express
express-handlebars        | A Handlebars view…   | =ericf =sahat…  | 2021-11-25 | 6.0.2    | express express3 handlebars view layout partials templates
is-regex                  | Is this value a JS…  | =ljharb         | 2021-08-06 | 1.1.4    | regex regexp is regular expression regular expression
express-fileupload        | Simple express file… | =richardgirges… | 2021-01-11 | 1.2.1    | express file-upload upload forms multipart files busboy middleware
express-http-proxy        | http proxy…          | =villadora…     | 2021-10-26 | 1.6.3    | express-http-proxy
connect-mongo             | MongoDB session…     | =jdesboeufs…    | 2021-09-17 | 4.6.0    | connect mongo mongodb session express
http-proxy-middleware     | The one-liner…       | =chimurai       | 2021-07-01 | 2.0.1    | reverse proxy middleware http https connect express fastify polka browser-sync gulp g
express-validator         | Express middleware…  | =ctavan…        | 2021-12-11 | 6.14.0   | express validator validation validate sanitize sanitization xss
path-to-regexp            | Express style path…  | =blakeembrey…   | 2020-09-29 | 6.2.0    | express regexp route routing
morgan                    | HTTP request logger… | =dougwilson     | 2020-03-20 | 1.10.0   | express http logger middleware
mathjs                    | Math.js is an…       | =josdejong      | 2021-12-29 | 10.0.2   | math mathematics functions numeric algebra parser expression number bignumber complex
multer                    | Middleware for…      | =hacksparrow…   | 2021-12-07 | 1.4.4    | form post multipart form-data formdata express middleware
helmet                    | help secure…         | =adam_baldwin…  | 2021-05-02 | 4.6.0    | express security headers
passport                  | Simple, unobtrusive… | =jaredhanson    | 2021-12-16 | 0.5.2    | express connect auth authn authentication
express-unless            | Conditionally add a… | =jfromaniello   | 2021-08-03 | 1.0.0    | 
webpack-hot-middleware    | Webpack hot…         | =glenjamin…     | 2021-09-14 | 2.25.1   | webpack hmr hot module reloading hot-reloading middleware express
serve-favicon             | favicon serving…     | =dougwilson     | 2018-03-29 | 2.5.0    | express favicon middleware
ignore                    | Ignore is a manager… | =kael           | 2021-12-19 | 5.2.0    | ignore .gitignore gitignore npmignore rules manager filter regexp regex fnmatch glob 

まとめ

npmを使う時に指定するバージョンについて、ちょっと調べてみました。

なんとなく雰囲気で使っていることが多かったので、1度しっかり見ておいて良かったかなと思います。

今後は、このあたりを意識して使っていきましょう。