yarn install 時にフック関数を実行しないようにする

例えばpackage.jsonに以下のように書いてあったとします。

"scripts": {
  "preinstall": "echo 1",
  "postinstall": "echo 2",
  "prepare": "echo 3",
}

そして、yarn(またはyarn install)すると、

yarn
# yarn install v1.12.3
# $ echo 1
# 1
# [1/4] 🔍  Resolving packages...
# success Already up-to-date.
# $ echo 2
# 2
# $ echo 3
# 3

という感じで全部実行されます。ローカルマシンでは自分で叩くようにしていると忘れていたりするのでこの動作は助かります。(特にpublish前のprepare) ただprepareでビルド処理とかしていると実行時間がただのyarnに比べて3,4倍になってしまっている感じもします。僕の CI 環境は、無料実行時間カツカツな状態なので、フックしなくていいから少しでも早く終わらせたいです。

--ignore-scripts

もう一度ドキュメントを読みました。そうしたら、どうやらこのオプションを使うといけるようです。 このオプションを使うと上記と同じscriptsの設定で、

yarn --ignore-scripts
# yarn install v1.12.3
# [1/4] 🔍  Resolving packages...
# success Already up-to-date.
# ✨  Done in 0.79s.

だけのログになりフックされないようにすることができました。

フックに依存しているパッケージを使っている時の注意

nowを CircleCI 上で使おうとした所インストール時のフック処理がされずにおかしなことになりました。どうやらこのオプションは依存のフックも無効化してしまうようです。このような場合は、それ単体で再度インストールコマンドを実行して入れる感じで対応するといいと思います。

resolutions で依存の依存のバージョンを指定する

例えば自分はnode@^10を使っていて、これを使いたいのに直接的な依存ではないパッケージのpackage.jsonenginesnode@<1010より小さい)と指定されているが為にyarnでのインストールが失敗するということが起こる時があります。

このエラーは一応yarn --ignore-enginesと、依存のenginesの指定を無視するオプションを付けると回避できますが、色んなプロジェクトを行き来していたりで「このプロジェクトではこのオプションが必要」などと覚えるのは面倒だったりするのでできれば解決したかったりします。

upath

僕が最近目撃したのはupath@1.0.4というパッケージ関連の事です。このupath@1.0.4ではengines>=4 <=9と指定されているようで、既にほかプロジェクトでは1011を使っていたので結構な頻度で引っかかりイライラしていました。

error upath@1.0.4: The engine "node" is incompatible with this module.
Expected version ">=4 <=9". Got "11.13.0"

しかもこれは直接追加したパッケージではなく、あるパッケージの依存パッケージの中で入っているであろうパッケージでいした。

しかし、そのあとにリリースされたこのパッケージのnodeensinesnode>=4へ修正されたので、そちらを使うようにすれば解決できそうです。

resolutions

yarn - 選択的な依存関係の解決

これをpackage.jsonresolutionsへ設定することで直接的な依存関係は弄らずにupathだけのバージョンを上げることができます。

現在のupathの最新バージョンは1.1.2です。upath@1.1.2を使うようにするためには以下のようにします。

{
  "resolutions": {
    "upath": "1.1.2"
  }
}

そしてyarnするだけです。yarnyarn.lockは以下のように更新されていました。

-upath@^1.0.0:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/upath/-/upath-1.0.4.tgz#ee2321ba0a786c50973db043a50b7bcba822361d"
-  integrity sha512-d4SJySNBXDaQp+DPrziv3xGS6w3d2Xt69FijJr86zMPBy23JEloMCEOUBBzuN7xCtjLCnmB9tI/z7SBCahHBOw==
+upath@1.1.2, upath@^1.0.0:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.2.tgz#3db658600edaeeccbe6db5e684d67ee8c2acd068"
+  integrity sha512-kXpym8n

一応他のバージョンは、

となっています。

npm に公開する

publicコマンドを使うと npm に公開できます。

そのまま使うと対話的に1つずつ確認しながら公開手順を踏めますが、オプションを渡してあげれば一度のコマンド実行で公開まで行ってくれます。

オプション

npmではバージョンはMAJOR.MINOR.PATCH@TAGという形で管理します。TAGはオプショナルです。例えば1.2.3ならMAJORバージョンは1MINORバージョンは2PATCHバージョンは3という意味です。

patch

patchオプションはPATCHバージョンを1つ上げて公開します。現在のバージョンが1.2.3なら1.2.4に上げてから公開します。

minor

minorオプションはMINOORバージョンを1つ上げて公開します。現在のバージョンが1.2.3なら1.3.0ですね。

major

これもMAJORバージョンを1つ上げて公開するやつです。現在のバージョンが1.2.3なら2.0.0です。

new-version

好きなバージョンを付けたい時に使います。yarn publish --new-version 2.3.4とすれば2.3.4バージョンで公開できます。

tag

VERSION@TAGの形で公開します。これは上記のどれかと一緒に使います。例えば現在のバージョンが1.2.3だとして、2.0.0@canaryとして公開したい場合、yarn publish --major --tag canaryを実行します。

公開後

Yarn のバージョンが1.15.2の現在、少なくともバージョンを上げた後のpackage.jsonpushなどは一緒にされないようなので忘れずにpushするようにしましょう。

ワークスペース

ワークスペース機能を使うと1つのプロジェクトで複数のnpmパッケージを管理できるようになり、かつnode_modulesを1箇所にまとめることができます。

設定

プロジェクトルートのpackage.jsonへは以下のような設定が必要になります。

{
  "private": true,
  "workspaces": [
    "packages/**/*",
    "example"
  ]
}

private:trueは必ず設定が必要です。workspacesへはパッケージとなる(package.jsonを持っている)ディレクトリへのパターンや相対パスを記述します。

これで例えば、examplepackages/foo/hogeといったディレクトリがpackage.jsonを持っていればnpm管理プロジェクトだとすることができます。
この状態でexamplepackages/foo/hoge双方でreactをインストールするとルートのnode_modulesだけにreactディレクトリが作られます。(bin系は各ディレクトリに作られる)

ルートへのパッケージインストール

ルートに共通パッケージをインストールしたい時などは-Wオプションが必要になります。

リンク

別に開発しているパッケージを手っ取り早く現在のパッケージで使えるようにします。monorepo の開発プロジェクトを別々にしているような感じです。

yarn link <package-name>とすることで、現在のパッケージのnode_modules/<package-name>へのシンボリックリンクを置きます。例えばローカルにしかない開発中のplus-oneを今のプロジェクトに持ってきたい場合は、plus-one側のルートで

yarn link

と実行します。これでyarn link <package-name><package-name>に指定可能なリストに登録されます。

あとは、現在のプロジェクトのルートで、

yarn link plus-one

としてあげれば完了です。

const plusOne = require('plus-one');

plusOne(1);

うまくリンクできない場合

package.jsonの必須項目の漏れがあると、うまくリンクできない場合がありました。僕の場合はversionを設定し忘れていた為に、binがうまくリンクされずしばらく悩みました。