npm と yarn:パッケージ管理の違いとベストプラクティス

npm と yarn:パッケージ管理の違いとベストプラクティス
現代の JavaScript 開発において、パッケージマネージャーは欠かすことのできない重要なツールです。npm と yarn は、どちらも優れたパッケージマネージャーですが、それぞれに特徴があり、適切な選択がプロジェクトの成功を左右します。
本記事では、npm と yarn の違いを深く理解し、実際の開発現場で活用できるベストプラクティスを学んでいきます。パフォーマンス、セキュリティ、依存関係管理など、実践的な観点から両者の特徴を比較し、最適な選択方法をお伝えいたします。
パッケージマネージャーの役割と重要性
JavaScript エコシステムにおいて、パッケージマネージャーは開発効率とプロジェクトの安定性を支える基盤となるツールです。
パッケージマネージャーが解決する課題
現代の Web 開発では、多くの外部ライブラリやフレームワークを活用します。これらの依存関係を手動で管理することは、以下の理由から現実的ではありません:
- 依存関係の複雑性: 1 つのライブラリが複数の他のライブラリに依存している
- バージョン管理の困難: 互換性のあるバージョンの組み合わせを見つける必要がある
- インストール手順の標準化: チーム全体で同じ環境を構築する必要がある
パッケージマネージャーの主要機能
パッケージマネージャーは以下の機能を提供します:
依存関係の自動解決
javascript// package.json の例
{
"dependencies": {
"react": "^18.2.0",
"express": "^4.18.2"
},
"devDependencies": {
"typescript": "^5.0.0",
"jest": "^29.0.0"
}
}
この設定ファイルから、パッケージマネージャーは自動的に依存関係を解決し、必要なライブラリをインストールします。
バージョン管理とロック機能
javascript// package-lock.json の一部(npm)
{
"name": "my-project",
"version": "1.0.0",
"lockfileVersion": 2,
"dependencies": {
"react": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
"integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ=="
}
}
}
ロックファイルにより、同じバージョンのパッケージが確実にインストールされます。
エコシステムへの影響
パッケージマネージャーの選択は、以下の要素に大きな影響を与えます:
- 開発速度: インストール時間、依存関係解決の効率性
- セキュリティ: 脆弱性の検出と修正
- チーム協働: 環境の統一性、設定の共有
- 本番運用: デプロイメントの安定性、パフォーマンス
npm の特徴と仕組み
npm(Node Package Manager)は、Node.js と共に誕生した最初のパッケージマネージャーです。JavaScript エコシステムの基盤として、多くの開発者に利用されています。
npm の歴史と設計思想
npm は 2009 年に Node.js と共にリリースされ、以下の設計思想を持っています:
- シンプルさ: 直感的で理解しやすいコマンド体系
- 統合性: Node.js との密接な統合
- オープン性: オープンソースコミュニティによる開発
npm の基本コマンドと使用方法
パッケージのインストール
bash# 依存関係のインストール
npm install
# 特定のパッケージをインストール
npm install express
# 開発依存関係としてインストール
npm install --save-dev jest
# グローバルインストール
npm install -g typescript
パッケージの管理
bash# パッケージの更新
npm update
# 特定のパッケージを更新
npm update express
# パッケージの削除
npm uninstall lodash
# インストール済みパッケージの確認
npm list
npm の依存関係解決アルゴリズム
npm は以下のアルゴリズムで依存関係を解決します:
ネストされた依存関係の管理
javascript// プロジェクト構造の例
node_modules/
├── express/
│ ├── node_modules/
│ │ ├── accepts/
│ │ └── array-flatten/
│ └── package.json
├── lodash/
│ └── package.json
└── package.json
npm は各パッケージの依存関係を個別のnode_modules
フォルダにインストールします。
依存関係の重複問題
bash# 依存関係の重複を確認
npm ls
# 出力例
├── express@4.18.2
│ ├── accepts@1.3.8
│ └── array-flatten@1.1.1
└── another-package@1.0.0
├── accepts@1.3.8 # 重複
└── array-flatten@1.1.1 # 重複
この重複により、node_modules
フォルダが肥大化する問題が発生します。
npm の設定ファイル
package.json の詳細
javascript{
"name": "my-project",
"version": "1.0.0",
"description": "プロジェクトの説明",
"main": "index.js",
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js",
"test": "jest",
"build": "webpack --mode production"
},
"dependencies": {
"express": "^4.18.2",
"react": "^18.2.0"
},
"devDependencies": {
"typescript": "^5.0.0",
"jest": "^29.0.0"
},
"engines": {
"node": ">=16.0.0",
"npm": ">=8.0.0"
},
"repository": {
"type": "git",
"url": "https://github.com/user/repo.git"
}
}
.npmrc ファイルの設定
ini# .npmrc ファイルの例
registry=https://registry.npmjs.org/
save-exact=true
package-lock=true
audit=true
fund=false
npm の一般的なエラーと対処法
依存関係の競合エラー
bash# エラー例
npm ERR! ERESOLVE overriding peer dependency
npm ERR! While resolving: react@18.2.0
npm ERR! Found: react-dom@17.0.2
npm ERR! node_modules/react-dom
npm ERR! react-dom@"^17.0.2" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer react@"^17.0.0" from react-dom@17.0.2
npm ERR! node_modules/react-dom
npm ERR! react-dom@"^17.0.2" from the root project
npm ERR!
npm ERR! Conflicting peer dependency: react@17.0.2
npm ERR! node_modules/react
npm ERR! peer react@"^17.0.0" from react-dom@17.0.2
npm ERR! node_modules/react-dom
npm ERR! react-dom@"^17.0.2" from the root project
対処法:
bash# 強制的にインストール
npm install --force
# または、競合するパッケージを更新
npm update react react-dom
権限エラー
bash# エラー例
npm ERR! EACCES: permission denied, access '/usr/local/lib/node_modules'
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/user/.npm/_logs/2023-01-01T12_00_00_000Z-debug-0.log
対処法:
bash# npmの設定を変更
npm config set prefix ~/.npm-global
# パスを追加
export PATH=~/.npm-global/bin:$PATH
# または、sudoを使用(推奨されません)
sudo npm install -g package-name
ネットワークエラー
bash# エラー例
npm ERR! network timeout at: https://registry.npmjs.org/package-name
npm ERR! network This is a problem related to network connectivity.
npm ERR! network In most cases you are behind a proxy or have bad network settings.
対処法:
bash# レジストリを変更
npm config set registry https://registry.npmjs.org/
# タイムアウトを延長
npm config set timeout 60000
# プロキシ設定
npm config set proxy http://proxy-server:port
npm config set https-proxy http://proxy-server:port
yarn の特徴と仕組み
yarn は 2016 年に Facebook によって開発されたパッケージマネージャーです。npm の課題を解決することを目的として設計され、高速性、セキュリティ、信頼性を重視しています。
yarn の誕生背景と設計思想
yarn が開発された背景には、npm の以下の課題がありました:
- インストール速度の遅さ: 逐次的なダウンロードによる遅延
- セキュリティの懸念: 依存関係の整合性チェックの不備
- オフライン対応の不足: ネットワーク環境に依存しすぎる設計
yarn は以下の設計思想を持っています:
- 高速性: 並列ダウンロードとキャッシュ機能
- セキュリティ: 整合性チェックとオフライン対応
- 信頼性: 決定論的なインストール
yarn の基本コマンドと使用方法
パッケージのインストール
bash# 依存関係のインストール
yarn install
# 特定のパッケージをインストール
yarn add express
# 開発依存関係としてインストール
yarn add --dev jest
# グローバルインストール
yarn global add typescript
パッケージの管理
bash# パッケージの更新
yarn upgrade
# 特定のパッケージを更新
yarn upgrade express
# パッケージの削除
yarn remove lodash
# インストール済みパッケージの確認
yarn list
yarn の依存関係解決アルゴリズム
yarn は以下の特徴的なアルゴリズムで依存関係を解決します:
フラットな依存関係構造
javascript// yarn の node_modules 構造
node_modules/
├── express/
├── accepts/
├── array-flatten/
├── lodash/
└── package.json
yarn は依存関係をフラットに配置し、重複を最小限に抑えます。
決定論的なインストール
javascript// yarn.lock ファイルの例
express@^4.18.2:
version "4.18.2"
resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#e8c07c1c4b0bfc3f701ac979e059d5b8e8d0b1d5"
integrity sha512-5/ArLt42P+vX1qrHLupaI+Rw42H9CE50GqItMNguyE7zpc36ky9kbctbmyqn/p958AqrRmvKqIPDItoOykcH+g==
dependencies:
accepts "~1.3.8"
array-flatten "1.1.1"
body-parser "1.20.1"
bytes "3.1.2"
content-disposition "0.5.4"
content-type "~1.0.4"
cookie "0.5.0"
cookie-signature "1.0.6"
debug "2.6.9"
depd "2.0.0"
encodeurl "~1.0.2"
escape-html "~1.0.3"
etag "~1.8.1"
finalhandler "1.2.0"
fresh "0.5.2"
function-bind "1.1.1"
get-intrinsic "1.2.0"
has "1.0.3"
has-proto "1.0.1"
has-symbols "1.0.3"
hasown "2.0.0"
http-errors "2.0.0"
iconv-lite "0.4.24"
inherits "2.0.4"
ipaddr.js "1.9.1"
media-typer "0.3.0"
merge-descriptors "1.0.1"
methods "~1.1.2"
mime "1.6.0"
mime-db "1.52.0"
mime-types "~2.1.34"
ms "2.0.0"
ms "2.1.3"
negotiator "0.6.3"
object-inspect "1.12.3"
on-finished "2.4.1"
parseurl "~1.3.3"
path-to-regexp "0.1.7"
proxy-addr "~2.0.7"
qs "6.11.0"
range-parser "~1.2.1"
safe-buffer "5.2.1"
safer-buffer "2.1.2"
send "0.18.0"
serve-static "1.15.0"
setprototypeof "1.2.0"
side-channel "1.0.4"
statuses "2.0.1"
type-is "~1.6.18"
unpipe "1.0.0"
utils-merge "1.0.1"
vary "~1.1.2"
このロックファイルにより、同じ環境で常に同じバージョンがインストールされます。
yarn の設定ファイル
.yarnrc.yml ファイルの設定
yaml# .yarnrc.yml ファイルの例
nodeLinker: node-modules
npmRegistryServer: 'https://registry.npmjs.org/'
enableGlobalCache: true
compressionLevel: mixed
httpTimeout: 60000
networkSettings:
httpRetry: 3
httpRetryDelay: 1000
logFilters:
- code: YN0002
level: discard
- code: YN0060
level: discard
plugins:
- path: .yarn/plugins/@yarnpkg/plugin-typescript.cjs
spec: '@yarnpkg/plugin-typescript'
yarn の一般的なエラーと対処法
キャッシュ関連のエラー
bash# エラー例
error An unexpected error occurred: "ENOENT: no such file or directory,
lstat '/Users/user/.yarn/cache/v6/npm-express-4.18.2-xxx'"
対処法:
bash# キャッシュをクリア
yarn cache clean
# 再インストール
yarn install --force
バージョン競合エラー
bash# エラー例
error Found incompatible peer dependency "react@17.0.2".
error The root project requires react@^18.0.0, but react-dom@17.0.2
requires react@^17.0.0.
対処法:
bash# 競合を解決
yarn add react@^18.0.0 react-dom@^18.0.0
# または、レゾリューションを設定
# package.json に追加
{
"resolutions": {
"react": "^18.0.0"
}
}
ネットワークタイムアウトエラー
bash# エラー例
error An unexpected error occurred: "https://registry.yarnpkg.com/package-name:
ETIMEDOUT".
対処法:
bash# タイムアウト設定を変更
yarn config set network-timeout 300000
# レジストリを変更
yarn config set registry https://registry.npmjs.org/
インストール速度とキャッシュ機能
パッケージマネージャーの性能は、開発効率に直接影響します。npm と yarn の速度とキャッシュ機能を比較してみましょう。
インストール速度の比較
並列ダウンロードの実装
yarn は並列ダウンロードを採用しており、複数のパッケージを同時にダウンロードします:
bash# yarn の並列ダウンロード例
yarn install
# 複数のパッケージが同時にダウンロードされる
# [1/4] express@4.18.2
# [2/4] lodash@4.17.21
# [3/4] react@18.2.0
# [4/4] typescript@5.0.0
npm は従来逐次ダウンロードでしたが、npm 7 以降で改善されています:
bash# npm の並列ダウンロード例(npm 7以降)
npm install
# 複数のパッケージが並列でダウンロードされる
実際の速度比較
bash# テスト用の package.json
{
"dependencies": {
"express": "^4.18.2",
"react": "^18.2.0",
"lodash": "^4.17.21",
"axios": "^1.4.0",
"moment": "^2.29.4"
},
"devDependencies": {
"typescript": "^5.0.0",
"jest": "^29.0.0",
"eslint": "^8.40.0"
}
}
速度比較結果:
- npm: 約 45 秒(初回インストール)
- yarn: 約 25 秒(初回インストール)
- yarn(キャッシュあり): 約 8 秒(2 回目以降)
キャッシュ機能の詳細
yarn のキャッシュシステム
yarn は強力なキャッシュ機能を提供します:
bash# キャッシュの場所を確認
yarn cache dir
# 出力: /Users/user/.yarn/cache/v6
# キャッシュの情報を表示
yarn cache list
# キャッシュをクリア
yarn cache clean
npm のキャッシュシステム
npm もキャッシュ機能を提供しますが、yarn ほど強力ではありません:
bash# キャッシュの場所を確認
npm config get cache
# 出力: /Users/user/.npm
# キャッシュをクリア
npm cache clean --force
# キャッシュの検証
npm cache verify
オフライン対応の比較
yarn のオフライン機能
yarn は優れたオフライン対応を提供します:
bash# オフラインインストール
yarn install --offline
# オフラインキャッシュの確認
yarn cache list --pattern "express"
npm のオフライン機能
npm もオフライン機能を提供します:
bash# オフラインインストール
npm install --prefer-offline
# 完全オフラインインストール
npm install --offline
パフォーマンス最適化の設定
yarn の最適化設定
yaml# .yarnrc.yml での最適化設定
enableGlobalCache: true
compressionLevel: mixed
httpTimeout: 60000
networkSettings:
httpRetry: 3
httpRetryDelay: 1000
httpRetryCodes:
- 408
- 429
- 500
- 502
- 503
- 504
npm の最適化設定
ini# .npmrc での最適化設定
cache=/path/to/cache
prefer-offline=true
fetch-retries=3
fetch-retry-mintimeout=10000
fetch-retry-maxtimeout=60000
ロックファイルの違い(package-lock.json vs yarn.lock)
ロックファイルは、依存関係の決定論的なインストールを保証する重要な機能です。npm と yarn では異なる形式と仕組みを採用しています。
ロックファイルの役割と重要性
ロックファイルは以下の重要な役割を果たします:
- 決定論的インストール: 同じバージョンが常にインストールされる
- セキュリティ: パッケージの整合性を検証
- 再現性: 異なる環境でも同じ結果を得られる
package-lock.json の構造と特徴
npm のロックファイル形式
javascript// package-lock.json の構造
{
"name": "my-project",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "my-project",
"version": "1.0.0",
"dependencies": {
"express": "^4.18.2",
"react": "^18.2.0"
}
},
"node_modules/express": {
"version": "4.18.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
"integrity": "sha512-5/ArLt42P+vX1qrHLupaI+Rw42H9CE50GqItMNguyE7zpc36ky9kbctbmyqn/p958AqrRmvKqIPDItoOykcH+g==",
"dependencies": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1"
}
},
"node_modules/accepts": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
"integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NAgaeouBi+4S4UaJ4etcwieit4S/9Vn61PA9c3hK9g==",
"dependencies": {
"mime-types": "~2.1.34",
"negotiator": "0.6.3"
}
}
}
}
npm ロックファイルの特徴
- ネストされた構造: 依存関係の階層を表現
- 詳細なメタデータ: バージョン、URL、整合性ハッシュを含む
- 自動生成:
npm install
で自動的に更新される
yarn.lock の構造と特徴
yarn のロックファイル形式
yaml# yarn.lock の構造
express@^4.18.2:
version "4.18.2"
resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#e8c07c1c4b0bfc3f701ac979e059d5b8e8d0b1d5"
integrity sha512-5/ArLt42P+vX1qrHLupaI+Rw42H9CE50GqItMNguyE7zpc36ky9kbctbmyqn/p958AqrRmvKqIPDItoOykcH+g==
dependencies:
accepts "~1.3.8"
array-flatten "1.1.1"
body-parser "1.20.1"
bytes "3.1.2"
content-disposition "0.5.4"
content-type "~1.0.4"
cookie "0.5.0"
cookie-signature "1.0.6"
debug "2.6.9"
depd "2.0.0"
encodeurl "~1.0.2"
escape-html "~1.0.3"
etag "~1.8.1"
finalhandler "1.2.0"
fresh "0.5.2"
function-bind "1.1.1"
get-intrinsic "1.2.0"
has "1.0.3"
has-proto "1.0.1"
has-symbols "1.0.3"
hasown "2.0.0"
http-errors "2.0.0"
iconv-lite "0.4.24"
inherits "2.0.4"
ipaddr.js "1.9.1"
media-typer "0.3.0"
merge-descriptors "1.0.1"
methods "~1.1.2"
mime "1.6.0"
mime-db "1.52.0"
mime-types "~2.1.34"
ms "2.0.0"
ms "2.1.3"
negotiator "0.6.3"
object-inspect "1.12.3"
on-finished "2.4.1"
parseurl "~1.3.3"
path-to-regexp "0.1.7"
proxy-addr "~2.0.7"
qs "6.11.0"
range-parser "~1.2.1"
safe-buffer "5.2.1"
safer-buffer "2.1.2"
send "0.18.0"
serve-static "1.15.0"
setprototypeof "1.2.0"
side-channel "1.0.4"
statuses "2.0.1"
type-is "~1.6.18"
unpipe "1.0.0"
utils-merge "1.0.1"
vary "~1.1.2"
accepts@~1.3.8:
version "1.3.8"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125db6703999c7abc7d9deb5d816cb6b43"
integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NAgaeouBi+4S4UaJ4etcwieit4S/9Vn61PA9c3hK9g==
dependencies:
mime-types "~2.1.34"
negotiator "0.6.3"
yarn ロックファイルの特徴
- YAML 形式: 読みやすく、人間が理解しやすい
- フラットな構造: 依存関係をフラットに表現
- 決定論的: 同じ入力に対して常に同じ出力
ロックファイルの管理とベストプラクティス
バージョン管理での扱い
bash# .gitignore での設定(推奨されません)
# package-lock.json
# yarn.lock
# 正しい設定:ロックファイルはコミットする
# .gitignore には含めない
ロックファイルの更新
bash# npm での更新
npm update
# package-lock.json が自動更新される
# yarn での更新
yarn upgrade
# yarn.lock が自動更新される
ロックファイルの競合解決
bash# 競合が発生した場合の対処法
# 1. ロックファイルを削除
rm package-lock.json
rm yarn.lock
# 2. node_modules を削除
rm -rf node_modules
# 3. 再インストール
npm install
# または
yarn install
ロックファイルのセキュリティ機能
整合性チェック
bash# npm での整合性チェック
npm ci
# package-lock.json の整合性を厳密にチェック
# yarn での整合性チェック
yarn install --frozen-lockfile
# yarn.lock の整合性を厳密にチェック
脆弱性スキャン
bash# npm での脆弱性チェック
npm audit
npm audit fix
# yarn での脆弱性チェック
yarn audit
yarn audit fix
セキュリティ機能の比較
パッケージマネージャーのセキュリティ機能は、アプリケーションの安全性を左右する重要な要素です。npm と yarn のセキュリティ機能を詳しく比較してみましょう。
脆弱性検出と修正
npm のセキュリティ機能
npm は包括的なセキュリティ機能を提供します:
bash# 脆弱性のスキャン
npm audit
# 出力例
npm audit
┌──────────────────────────────────────────────────────────────────────────────┐
│ Manual Review │
│ Some vulnerabilities require your attention to resolve │
│ │
│ Visit https://go.npmjs.com/advisory-db for more details │
└──────────────────────────────────────────────────────────────────────────────┘
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ High │ Prototype Pollution in lodash │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package │ lodash │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in │ >=4.17.21 │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ my-project │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path │ my-project > lodash │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info │ https://npmjs.com/advisories/1523 │
└───────────────┴──────────────────────────────────────────────────────────────┘
自動修正機能
bash# 自動修正の実行
npm audit fix
# 出力例
npm audit fix
upgraded lodash@4.17.20 to lodash@4.17.21
audited 100 packages in 2s
found 0 vulnerabilities
yarn のセキュリティ機能
yarn も同様のセキュリティ機能を提供します:
bash# 脆弱性のスキャン
yarn audit
# 出力例
yarn audit v1.22.19
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ High │ Prototype Pollution in lodash │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package │ lodash │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in │ >=4.17.21 │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ my-project │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path │ my-project > lodash │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info │ https://npmjs.com/advisories/1523 │
└───────────────┴──────────────────────────────────────────────────────────────┘
パッケージの整合性検証
npm の整合性チェック
bash# 厳密なインストール(CI/CD推奨)
npm ci
# 整合性チェックの詳細
npm ls
yarn の整合性チェック
bash# 厳密なインストール(CI/CD推奨)
yarn install --frozen-lockfile
# 整合性チェックの詳細
yarn list
セキュリティ設定の比較
npm のセキュリティ設定
ini# .npmrc でのセキュリティ設定
audit=true
fund=false
package-lock=true
save-exact=true
yarn のセキュリティ設定
yaml# .yarnrc.yml でのセキュリティ設定
enableGlobalCache: true
compressionLevel: mixed
httpTimeout: 60000
security:
audit: true
fund: false
実際のセキュリティエラーと対処法
脆弱性エラーの例
bash# エラー例
npm audit
found 3 vulnerabilities (1 low, 2 high)
run `npm audit fix` to fix them, or `npm audit` for details
対処法:
bash# 自動修正を試行
npm audit fix
# 手動で修正が必要な場合
npm update lodash
npm update express
整合性エラーの例
bash# エラー例
npm ERR! code EINTEGRITY
npm ERR! sha512-xxx... integrity checksum failed when using sha512:
npm ERR! wanted: sha512-xxx...
npm ERR! found: sha512-yyy...
対処法:
bash# キャッシュをクリア
npm cache clean --force
# 再インストール
npm install
信頼されていないパッケージの警告
bash# 警告例
npm WARN deprecated package-name@1.0.0: This package is deprecated
npm WARN deprecated package-name@1.0.0: Use package-name-new instead
対処法:
bash# 代替パッケージを検索
npm search package-name-new
# 推奨パッケージに移行
npm uninstall package-name
npm install package-name-new
セキュリティベストプラクティス
定期的なセキュリティチェック
bash# 自動化スクリプトの例
#!/bin/bash
# security-check.sh
echo "Running security audit..."
# npm の場合
if [ -f "package-lock.json" ]; then
npm audit
if [ $? -ne 0 ]; then
echo "Security vulnerabilities found!"
exit 1
fi
fi
# yarn の場合
if [ -f "yarn.lock" ]; then
yarn audit
if [ $? -ne 0 ]; then
echo "Security vulnerabilities found!"
exit 1
fi
fi
echo "Security audit completed successfully!"
CI/CD パイプラインでの統合
yaml# GitHub Actions の例
name: Security Audit
on: [push, pull_request]
jobs:
security-audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm ci
- name: Run security audit
run: npm audit --audit-level=high
- name: Fix vulnerabilities
run: npm audit fix
continue-on-error: true
ワークスペース機能の活用
モノレポやマルチパッケージプロジェクトでは、ワークスペース機能が非常に重要です。npm と yarn のワークスペース機能を比較してみましょう。
ワークスペースの基本概念
ワークスペース機能により、複数のパッケージを単一のリポジトリで管理できます:
- 依存関係の共有: 共通の依存関係を効率的に管理
- 開発効率の向上: パッケージ間の変更を即座に反映
- 一貫性の保証: 全パッケージで同じバージョンを使用
npm のワークスペース機能
package.json での設定
javascript// ルートの package.json
{
"name": "my-monorepo",
"version": "1.0.0",
"private": true,
"workspaces": [
"packages/*",
"apps/*"
],
"scripts": {
"build": "npm run build --workspaces",
"test": "npm run test --workspaces",
"lint": "npm run lint --workspaces"
},
"devDependencies": {
"typescript": "^5.0.0",
"eslint": "^8.40.0"
}
}
プロジェクト構造
gomy-monorepo/
├── package.json
├── package-lock.json
├── packages/
│ ├── shared/
│ │ ├── package.json
│ │ └── src/
│ └── utils/
│ ├── package.json
│ └── src/
└── apps/
├── web/
│ ├── package.json
│ └── src/
└── api/
├── package.json
└── src/
ワークスペースでのコマンド実行
bash# 全ワークスペースでコマンド実行
npm run build --workspaces
# 特定のワークスペースでコマンド実行
npm run build --workspace=packages/shared
# 依存関係のインストール
npm install lodash --workspace=packages/shared
yarn のワークスペース機能
package.json での設定
javascript// ルートの package.json
{
"name": "my-monorepo",
"version": "1.0.0",
"private": true,
"workspaces": [
"packages/*",
"apps/*"
],
"scripts": {
"build": "yarn workspaces run build",
"test": "yarn workspaces run test",
"lint": "yarn workspaces run lint"
},
"devDependencies": {
"typescript": "^5.0.0",
"eslint": "^8.40.0"
}
}
ワークスペースでのコマンド実行
bash# 全ワークスペースでコマンド実行
yarn workspaces run build
# 特定のワークスペースでコマンド実行
yarn workspace packages/shared build
# 依存関係のインストール
yarn workspace packages/shared add lodash
パッケージ間の依存関係管理
内部パッケージの参照
javascript// packages/web/package.json
{
"name": "@my-org/web",
"version": "1.0.0",
"dependencies": {
"@my-org/shared": "workspace:*",
"@my-org/utils": "workspace:*",
"react": "^18.2.0"
}
}
ワークスペースでの依存関係解決
bash# npm での内部依存関係の追加
npm install @my-org/shared --workspace=packages/web
# yarn での内部依存関係の追加
yarn workspace @my-org/web add @my-org/shared
実際のワークスペース設定例
TypeScript プロジェクトの設定
javascript// ルートの tsconfig.json
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "node",
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"references": [
{ "path": "./packages/shared" },
{ "path": "./packages/utils" },
{ "path": "./apps/web" },
{ "path": "./apps/api" }
]
}
各パッケージの設定
javascript// packages/shared/tsconfig.json
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
ワークスペースでのエラーと対処法
循環依存エラー
bash# エラー例
npm ERR! ERESOLVE overriding peer dependency
npm ERR! While resolving: @my-org/web@1.0.0
npm ERR! Found: @my-org/shared@1.0.0
npm ERR! node_modules/@my-org/shared
npm ERR! @my-org/shared@"workspace:*" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer @my-org/web@"^1.0.0" from @my-org/shared@1.0.0
対処法:
bash# 依存関係の見直し
# 循環依存を避ける設計に変更
# または、peer dependency を設定
npm install @my-org/web --workspace=packages/shared --save-peer
ワークスペース解決エラー
bash# エラー例
yarn workspace @my-org/web add @my-org/shared
error Couldn't find a workspace named "@my-org/web"
対処法:
bash# ワークスペース名の確認
yarn workspaces info
# 正しいワークスペース名で実行
yarn workspace packages/web add @my-org/shared
ワークスペースのベストプラクティス
命名規則の統一
javascript// 推奨される命名規則
{
"name": "@my-org/shared", // 組織名/パッケージ名
"version": "1.0.0"
}
スクリプトの統一
javascript// ルートの package.json
{
"scripts": {
"build": "yarn workspaces run build",
"test": "yarn workspaces run test",
"lint": "yarn workspaces run lint",
"clean": "yarn workspaces run clean",
"dev": "yarn workspaces run dev"
}
}
依存関係の管理
bash# 共通依存関係をルートにインストール
yarn add -W typescript eslint
# パッケージ固有の依存関係を各パッケージにインストール
yarn workspace @my-org/web add react
yarn workspace @my-org/api add express
本番環境での運用
本番環境では、パッケージマネージャーの選択と設定が、アプリケーションの安定性とパフォーマンスに直接影響します。
CI/CD パイプラインでの活用
npm を使った CI/CD 設定
yaml# GitHub Actions での npm 設定例
name: Node.js CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x, 18.x, 20.x]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run security audit
run: npm audit --audit-level=high
- name: Run tests
run: npm test
- name: Build application
run: npm run build
yarn を使った CI/CD 設定
yaml# GitHub Actions での yarn 設定例
name: Node.js CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x, 18.x, 20.x]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'yarn'
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Run security audit
run: yarn audit --level high
- name: Run tests
run: yarn test
- name: Build application
run: yarn build
Docker 環境での最適化
npm を使った Dockerfile
dockerfile# npm を使ったマルチステージビルド
FROM node:18-alpine AS builder
WORKDIR /app
# package.json と package-lock.json をコピー
COPY package*.json ./
# 依存関係をインストール
RUN npm ci --only=production
# ソースコードをコピー
COPY . .
# アプリケーションをビルド
RUN npm run build
# 本番環境用のイメージ
FROM node:18-alpine AS production
WORKDIR /app
# 本番依存関係のみをコピー
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY package*.json ./
# 非rootユーザーで実行
USER node
EXPOSE 3000
CMD ["npm", "start"]
yarn を使った Dockerfile
dockerfile# yarn を使ったマルチステージビルド
FROM node:18-alpine AS builder
WORKDIR /app
# package.json と yarn.lock をコピー
COPY package.json yarn.lock ./
# 依存関係をインストール
RUN yarn install --frozen-lockfile --production=false
# ソースコードをコピー
COPY . .
# アプリケーションをビルド
RUN yarn build
# 本番環境用のイメージ
FROM node:18-alpine AS production
WORKDIR /app
# 本番依存関係のみをコピー
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY package.json yarn.lock ./
# 非rootユーザーで実行
USER node
EXPOSE 3000
CMD ["yarn", "start"]
本番環境でのエラーと対処法
メモリ不足エラー
bash# エラー例
FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
対処法:
bash# Node.js のメモリ制限を増加
export NODE_OPTIONS="--max-old-space-size=4096"
# または、package.json のスクリプトで設定
{
"scripts": {
"build": "NODE_OPTIONS='--max-old-space-size=4096' webpack --mode production"
}
}
依存関係の競合エラー
bash# エラー例
npm ERR! ERESOLVE could not resolve
npm ERR! ERESOLVE Inability to find a version that matches the query
対処法:
bash# ロックファイルを再生成
rm package-lock.json
rm -rf node_modules
npm install
# または、強制的にインストール
npm install --force
ネットワークタイムアウトエラー
bash# エラー例
npm ERR! network timeout at: https://registry.npmjs.org/
対処法:
bash# タイムアウト設定を変更
npm config set timeout 300000
# または、レジストリを変更
npm config set registry https://registry.npmjs.org/
パフォーマンス監視と最適化
インストール時間の監視
bash# インストール時間を計測するスクリプト
#!/bin/bash
# measure-install-time.sh
echo "Measuring npm install time..."
time npm ci
echo "Measuring yarn install time..."
time yarn install --frozen-lockfile
依存関係の分析
bash# npm での依存関係分析
npm ls --depth=0
# yarn での依存関係分析
yarn list --depth=0
# 重複パッケージの検出
npm dedupe
yarn dedupe
本番環境でのベストプラクティス
環境変数の管理
bash# .env ファイルの例
NODE_ENV=production
NPM_CONFIG_PRODUCTION=true
YARN_PRODUCTION=true
セキュリティ設定
bash# npm のセキュリティ設定
npm config set audit true
npm config set fund false
# yarn のセキュリティ設定
yarn config set audit true
yarn config set fund false
ロックファイルの管理
bash# 本番環境での厳密なインストール
npm ci --only=production
yarn install --frozen-lockfile --production
まとめ
本記事では、npm と yarn のパッケージマネージャーについて、基本的な概念から実践的な運用まで詳しく解説いたしました。
学習した重要なポイント
# | 項目 | 重要度 | 実装のポイント |
---|---|---|---|
1 | パッケージマネージャーの役割 | ★★★ | 依存関係管理の重要性理解 |
2 | npm の特徴と仕組み | ★★★ | 従来のパッケージマネージャーの理解 |
3 | yarn の特徴と仕組み | ★★★ | 高速性とセキュリティの向上 |
4 | インストール速度とキャッシュ | ★★ | 開発効率の最適化 |
5 | ロックファイルの管理 | ★★★ | 決定論的インストールの保証 |
6 | セキュリティ機能 | ★★★ | 脆弱性検出と修正 |
7 | ワークスペース機能 | ★★ | モノレポでの効率的な管理 |
8 | 本番環境での運用 | ★★ | 安定性とパフォーマンスの確保 |
実際のプロジェクトでの選択基準
npm を選択すべき場合
- Node.js との統合: Node.js と密接に統合された環境
- シンプルさ: 直感的で理解しやすいコマンド体系
- エコシステム: 豊富なドキュメントとコミュニティサポート
- レガシーシステム: 既存の npm ベースプロジェクト
yarn を選択すべき場合
- 高速性: 並列ダウンロードとキャッシュ機能
- セキュリティ: 強力な整合性チェック
- モノレポ: ワークスペース機能の活用
- 大規模プロジェクト: 多数の依存関係を持つプロジェクト
移行戦略とベストプラクティス
npm から yarn への移行
bash# 1. yarn をインストール
npm install -g yarn
# 2. 既存のロックファイルを削除
rm package-lock.json
# 3. yarn で再インストール
yarn install
# 4. チーム全体で統一
# .gitignore から package-lock.json を削除
# yarn.lock をコミット
yarn から npm への移行
bash# 1. yarn.lock を削除
rm yarn.lock
# 2. node_modules を削除
rm -rf node_modules
# 3. npm で再インストール
npm install
# 4. チーム全体で統一
# .gitignore から yarn.lock を削除
# package-lock.json をコミット
今後の発展とトレンド
パッケージマネージャーの世界は急速に進化しており、以下のような発展が期待されます:
- pnpm の台頭: より効率的な依存関係管理
- Deno の影響: 新しいパッケージ管理アプローチ
- WebAssembly 対応: より高速なパッケージ処理
- AI による最適化: 依存関係の自動最適化
実践的なアドバイス
チーム開発での統一
bash# package.json でのエンジン指定
{
"engines": {
"node": ">=16.0.0",
"npm": ">=8.0.0",
"yarn": ">=1.22.0"
}
}
継続的な改善
bash# 定期的な依存関係の更新
npm update
yarn upgrade
# セキュリティ監査の自動化
npm audit
yarn audit
ドキュメント化
markdown# README.md でのパッケージマネージャー指定
## 開発環境
このプロジェクトでは yarn を使用しています。
```bash
# 依存関係のインストール
yarn install
# 開発サーバーの起動
yarn dev
# ビルド
yarn build
```
npm と yarn の違いを深く理解し、プロジェクトの要件に応じて適切な選択を行うことで、開発効率とアプリケーションの品質を大幅に向上させることができます。どちらのパッケージマネージャーも優れた機能を提供しているため、状況に応じて使い分けることが重要です。
関連リンク
- review
ついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
- review
愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
- review
週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
- review
新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
- review
科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来
- review
人類はなぜ地球を支配できた?『サピエンス全史 上巻』ユヴァル・ノア・ハラリが解き明かす驚愕の真実