
まだ 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_packageornpm uninstall --save new_packagenpm ls
- package.json からインストール
- dependencies に new_package を追加/削除する
npm update --save(危険)npm ls(失敗しがち)
- コマンドからインストール
-
yarn の場合
- コマンドからインストール
yarn add new_packageoryarn remove new_packageyarn check
- package.json からインストール
- dependencies に new_package を追加/削除する
yarn upgradeyarn check
- コマンドからインストール
shrinkwrap を使った場合には package.json に手動でパッケージを追加すると、それを削除した際に追従できずにエラーが発生することがありますが、yarn を使った場合に同じ作業を行っても問題が発生しません。
依存関係地獄 (dependency hell)
npm-shrinkwrap.json を使うことで確かに npm install で同じパッケージ群をインストールすることはできるようになります。
この環境に package.json への追加によって新しいパッケージを追加しようとした場合には shrinkwrap は正しく依存関係を更新できません。
以下の手順で依存性解決をすることになります。
- 本体またはサブモジュールの
package.jsonを更新する npm installornpm 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
をご覧ください。 もしくはお気軽に、下記の「話を聞きに行きたい」ボタンを押してください!