
まだ node.js の依存性解決で消耗してるの?
Posted on
PLAID エンジニア/HUNTER
山内 雅浩
@algas
概要
node.js (npm) での依存性解決とパッケージマネージャを shrinkwrap から yarn へ移行した話。
プレイド勉強会での発表資料 も合わせてご覧ください。
対象読者
- node.js で継続的に開発を行っているエンジニア
- npm 依存関係地獄に苦しんでいる同志
結論
shrinkwrap を捨てて yarn を使いましょう。
ただし production に使うのはちょっと早い。
執筆時点での yarn のバージョンは 0.17.10 です。
shrinkwrap vs yarn
(npm) shrinkwrap と yarn を比較してみましょう。
項目名 | Node.js | Yarn |
---|---|---|
パッケージマネージャ名 | npm | yarn |
パッケージファイル | package.json | package.json |
パッケージ指定ファイル | npm-shrinkwrap.json | yarn.lock |
yarn を使う利点と欠点は以下のとおりです。
PROS
- インストール処理が高速かつ安定
ネットワークパフォーマンス改善やオフラインモード、リトライの実装がされていてパッケージのインストールが標準のnpm install
に比べて高速かつ安定に動作します。 - 依存性解決の向上
複数のパッケージで使われている同じパッケージを1つのインデックスにまとめることでインストールするパッケージ数を減らし、ディスク容量の軽減・インストール速度の向上を実現しています。
CONS
- yarn 自体のインストールが必要
他のパッケージよりも先に yarn をインストールしなければなりません。shrinkwrap は npm に標準装備されているのでインストールは必要ありません。 npm ls
とyarn ls
の互換性がない
npm install
済みのパッケージを確認するコマンドであるnpm ls
とyarn install
済みのパッケージを確認するyarn ls
に互換性がありません。yarn install
が正常にできた環境でnpm ls
を実施しても OK と返らない場合があります。- yarn 自体の不具合
yarn のバージョンは執筆時点で 0.x であり、正式バージョンである 1.0 以上になっていません。公開されて間もないこともあり、issue が大量に上げられていて yarn 自体の不具合に悩まされることもあります。
node パッケージの追加と削除
パッケージを追加・削除する方法にはコマンドからインストールするのと、package.json に書いてからインストールする2通りの方法があります。
CIなどのリモート環境では後者の方法で運用する場合もあります。
-
npm + shrinkwrap の場合
- コマンドからインストール
npm install --save new_package
ornpm uninstall --save new_package
npm ls
- package.json からインストール
- dependencies に new_package を追加/削除する
npm update --save
(危険)npm ls
(失敗しがち)
- コマンドからインストール
-
yarn の場合
- コマンドからインストール
yarn add new_package
oryarn remove new_package
yarn check
- package.json からインストール
- dependencies に new_package を追加/削除する
yarn upgrade
yarn check
- コマンドからインストール
shrinkwrap を使った場合には package.json に手動でパッケージを追加すると、それを削除した際に追従できずにエラーが発生することがありますが、yarn を使った場合に同じ作業を行っても問題が発生しません。
依存関係地獄 (dependency hell)
npm-shrinkwrap.json
を使うことで確かに npm install
で同じパッケージ群をインストールすることはできるようになります。
この環境に package.json への追加によって新しいパッケージを追加しようとした場合には shrinkwrap は正しく依存関係を更新できません。
以下の手順で依存性解決をすることになります。
- 本体またはサブモジュールの
package.json
を更新する npm install
ornpm update --save
を実行する- パッケージの更新に失敗する
- 1.に戻る(依存性解決できるまで繰り返す)
結局、問題が解決できずに npm-shrinkwrap.json
を削除するしかない状況に陥ることも多くあります。
これが継続的に依存性問題を解決できない理由です。
依存性解決できない問題
node.js でデファクトスタンダードになっているパッケージ管理ツールである npm (node package manager) で依存性を解決するのが難しいという問題があります。
現状では shrinkwrap という npm に標準装備されている方法を使ってインストールされるパッケージを固定(バージョン指定のスナップショット)できます。
npm shrinkwrap
コマンドでパッケージ指定ファイル npm-shrinkwrap.json
を生成することで、他の環境で npm install
を実行した際に(依存関係も含めて)同じパッケージがインストールされるようにします。
上記で書いたとおりに shrinkwrap を使えばインストールされるパッケージを固定することはできます。しかし上述の通り、実際に運用してみると shrinkwrap ではパッケージの固定はできても、継続的な依存性解決ができるわけではないことがわかります。
Yarn の不具合
- production install できない
yarn install --production
が効かない。つまり devDependencies もインストールされる。
https://github.com/yarnpkg/yarn/issues/761 - postinstall を実行してない問題
deep dependencies で preinstall, install, postinstall を実行できてない。
https://github.com/yarnpkg/yarn/issues/2142
自作ツールの紹介
緩やかに移行したい方へ npm-shrinkwrap.json
から yarn.lock
を生成するツールを作りました。
https://github.com/algas/shrinkwrap2yarn
使い方は上記リポジトリの README をご参照ください。
動かなかったり不具合を見つけたりした場合には issue, PR をお待ちしております。
自社の製品では~~shrinkwrap.json
の作成フローが雑だったので~~結局使いませんでした。
ハマったこと
- npm でのインストールの挙動(サブコマンドの動作など)が把握できなくて、理解するまでにすごく時間がかかりました。
- 自社の node.js プロジェクトの依存性解決に手間取りました。
- うちの package.json はいろんな処理を書きすぎじゃね?
参考文献
まとめ
今すぐ shrinkwrap
を捨てて yarn
と旅に(ry
エンジニア募集中
ウェブ接客プラットフォーム「KARTE」を運営するプレイドでは、KARTEを使ってこんなアプリケーションが作りたい! KARTE自体の開発に興味がある!というエンジニア(インターンも!)を募集しています。
詳しくは弊社採用ページ
またはWantedly
をご覧ください。 もしくはお気軽に、下記の「話を聞きに行きたい」ボタンを押してください!