🧚‍♀️

Yarnで学ぶパッケージマネージャーの動作

2022/06/28に公開

今となっては感覚で使っていますが、
いざ新人さんなどにパッケージマネージャーを説明すると少々伝わりにくいことがあるので、
今回はYarnを使ってパッケージマネージャーの動作を説明します。
パッケージマネージャーはYarnだろうがPHPのComposerだろうが大体似通った動きをしますので、
基本動作を抑えておくと応用が効くでしょう。

初期化

yarn init

プロジェクトのディレクトリで初期化コマンドを実行します。
初期化コマンド実行で大体設定ファイルができます。
Yarnの場合はpackage.jsonです。

パッケージの追加

yarn add @vue/cli@3.4.0

yarn addを使います。
パッケージ名の後に@でバージョンを指定可能です。
省略した場合は基本的に最新がインストールされます。

パッケージを追加すると、package.jsonが更新されます。

package.json
{
  "name": "yarn-dev",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "dependencies": {
    "@vue/cli": "3.4.0" 
  }
}

実際にインストールしたバージョンはロックファイルを見るとわかります。

yarn.lock
"@vue/cli@3.4.0":
  version "3.4.0"
  resolved "https://registry.yarnpkg.com/@vue/cli/-/cli-3.4.0.tgz#735ab451570001c5a49c74742f713f72a6fa3139"

パッケージのファイルそのものはnode_modulesフォルダにできます。

ここからパッケージを増やした場合、パッケージマネージャーはパッケージ同士の依存関係を解消しながらインストールを行います。
従って、場合によっては最新がインストールされなかったり競合エラーになることもあります。

パッケージの変更

package.jsonのバージョンを変更してyarn installすると、パッケージのバージョンが変わります^3.4.0で3.4.0以上の意味となり、他のパッケージがあればそれらと矛盾しない範囲で最新バージョンになります。
バージョンの指定は範囲などいろんな書き方できます。
こちらを参考にしてみてください。

package.json
{
  "name": "yarn-dev",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "dependencies": {
    "@vue/cli": "^3.4.0" 
  }
}
yarn.lock
"@vue/cli@^3.4.0":
  version "3.12.1"
  resolved "https://registry.yarnpkg.com/@vue/cli/-/cli-3.12.1.tgz#a4df8ada081e59855ae95d8a46b54ec6c37d2bc5"

インストールした状態を再現するには

インストールした状態を再現するにはpackage.jsonとyarn.lockを使用します。
package.jsonとyarn.lockがあれば、そこでyarn installすれば、
同じ状態を再現することができます。
従ってyarnの場合ソース管理するのはpackage.jsonとyarn.lockです。
node_modulesは不要です。

lockファイルについて

yarn.lockはインストールしたパッケージの具体的なバージョンが書かれています。
これがある状態でyarn installすると優先して参照されてインストール状態を再現することができます。
パッケージは非常に複雑な依存関係を持っています。
一つパッケージをインストールするだけでも結構な依存関係があるので、
lockファイルがないと例えpackage.jsonで同じバージョンを指定しても依存関係のせいで完全に同じ状態にはならないことが起きえます。
極力lockファイルもソース管理に含めるのがよいでしょう。

パッケージ全体の更新

yarn upgrade

を使います。
このコマンドはpackage.jsonで指定した範囲内で全体を最新バージョンで更新します。
依存関係などが新しくなります。
package.jsonそのものは変わらずlockファイルが変わります。

package.jsonを超えて全体を最新化する場合はオプションを追加します。
この場合、package.jsonも変わります。

yarn upgrade --latest

パッケージの読み込み

パッケージマネージャーを使ってインストールしたものを自分のプログラムから呼び出す場合は、
それ相応の呼び方をします。
通常Yarnならimport、PHPのComposerならautoloadを使用します。
node_modules配下のファイルを<script>タグで直接ロードすることも可能ですが、
これだと依存関係が正しく読み込まれなかったり、最終的にロードモジュールを作るのに苦労したりとパッケージマネージャーを使用する意味が薄れていきます。

開発用パッケージ

yarn addでオプション--devをつけると開発環境用のパッケージ(devDependencies)として登録できてます。

yarn add eslint --dev
{
    "name": "yarn-dev",
    "version": "1.0.0",
    "main": "index.js",
    "license": "MIT",
    "dependencies": {
        "@vue/cli": "3.4.0"
    },
    "devDependencies": {
        "eslint": "^8.18.0"
    }
}

開発用のパッケージは、yarn installする時にオプション--productionをつけると、
本番用のインストールが実行されて開発用パッケージを含めないようにすることができます。
本番環境でinstallする場合は--productionをつけて余計なものを含めないようにすると良いでしょう。

コマンドを登録しておく

{
  "name": "example",
    "version": "1.0.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve --mode development",
    "build": "vue-cli-service build --mode production",
    "lint": "vue-cli-service lint --fix",
  },
  "dependencies": {
    "core-js": "^3.6.5",
    "vue": "^3.0.0"
  },

package.jsonにはscriptsという欄があり、コマンドを登録しておくことができます。
セミコロンで区切れば複数のコマンドを登録可能です。
ここに登録しておけば

yarn コマンド名

という形で実行することができます。
yarn serve?yarnにそんなサブコマンドなんてあったっけ?と思ったら、package.jsonを見てみてください。

活用方法

例えばVueであれば本番用のビルドと配信サーバーへのアップロードをセットにして登録しておくと、一発で実行できて便利です。

{
    "name": "example",
    "version": "1.0.0",
    "private": true,
    "scripts": {
      "serve": "vue-cli-service serve --mode development",
      "build": "vue-cli-service build --mode production",
      "lint": "vue-cli-service lint --fix",
      "deploy": "vue-cli-service build --mode production; aws s3 sync dist s3://bucketname"
    },

本記事で紹介するのはここまでです。
パッケージマネージャーはどれでも良いので一つ抑えておくと、新しいプロジェクトに入った時などに早く馴染めると思います。

Discussion