npm workspaceとnpm installの挙動確認
環境
% node -v v16.13.0 % npm -v 8.11.0
概要
npm workspaceでnpm installを実行すると
1. ワークスペースルート
2. (バージョンが異なるものは)各々のワークスペース
の順にインストールされる
構成
npm-workspace % tree . -a -I node_modules . ├── .gitignore ├── .npmrc ├── app-a │ └── package.json ├── app-b │ └── package.json ├── package-lock.json └── package.json
save-exact=true
{ "name": "npm-workspace", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "workspaces": [ "app-a", "app-b" ] }
挙動の確認
%npm i rimraf -w app-a %npm i rimraf@2 -w app-b
結果A
% tree . . ├── app-a │ └── package.json ├── app-b │ ├── node_modules │ │ └── rimraf │ │ ├── LICENSE │ │ ├── README.md │ │ ├── bin.js │ │ ├── package.json │ │ └── rimraf.js │ └── package.json ├── node_modules │ ├── app-a -> ../app-a │ ├── app-b -> ../app-b │ ├── balanced-match │ │ ├── LICENSE.md │ │ ├── README.md │ │ ├── index.js │ │ └── package.json │ ├── brace-expansion │ │ ├── LICENSE │ │ ├── README.md │ │ ├── index.js │ │ └── package.json │ ├── concat-map │ │ ├── LICENSE │ │ ├── README.markdown │ │ ├── example │ │ │ └── map.js │ │ ├── index.js │ │ ├── package.json │ │ └── test │ │ └── map.js │ ├── fs.realpath │ │ ├── LICENSE │ │ ├── README.md │ │ ├── index.js │ │ ├── old.js │ │ └── package.json │ ├── glob │ │ ├── LICENSE │ │ ├── README.md │ │ ├── common.js │ │ ├── glob.js │ │ ├── package.json │ │ └── sync.js │ ├── inflight │ │ ├── LICENSE │ │ ├── README.md │ │ ├── inflight.js │ │ └── package.json │ ├── inherits │ │ ├── LICENSE │ │ ├── README.md │ │ ├── inherits.js │ │ ├── inherits_browser.js │ │ └── package.json │ ├── minimatch │ │ ├── LICENSE │ │ ├── README.md │ │ ├── minimatch.js │ │ └── package.json │ ├── once │ │ ├── LICENSE │ │ ├── README.md │ │ ├── once.js │ │ └── package.json │ ├── path-is-absolute │ │ ├── index.js │ │ ├── license │ │ ├── package.json │ │ └── readme.md │ ├── rimraf │ │ ├── CHANGELOG.md │ │ ├── LICENSE │ │ ├── README.md │ │ ├── bin.js │ │ ├── package.json │ │ └── rimraf.js │ └── wrappy │ ├── LICENSE │ ├── README.md │ ├── package.json │ └── wrappy.js ├── package-lock.json └── package.json 21 directories, 65 files
package-lock.jsonを削除し、コマンドの実行順を変えてみる
% rm package-lock.json % rm -rf node_modules && rm -rf app-b/node_modules
%npm i rimraf@2 -w app-b %npm i rimraf -w app-a
結果
% tree . . ├── app-a │ ├── node_modules │ │ └── rimraf │ │ ├── CHANGELOG.md │ │ ├── LICENSE │ │ ├── README.md │ │ ├── bin.js │ │ ├── package.json │ │ └── rimraf.js │ └── package.json ├── app-b │ └── package.json ├── node_modules │ ├── app-a -> ../app-a │ ├── app-b -> ../app-b │ ├── balanced-match │ │ ├── LICENSE.md │ │ ├── README.md │ │ ├── index.js │ │ └── package.json │ ├── brace-expansion │ │ ├── LICENSE │ │ ├── README.md │ │ ├── index.js │ │ └── package.json │ ├── concat-map │ │ ├── LICENSE │ │ ├── README.markdown │ │ ├── example │ │ │ └── map.js │ │ ├── index.js │ │ ├── package.json │ │ └── test │ │ └── map.js │ ├── fs.realpath │ │ ├── LICENSE │ │ ├── README.md │ │ ├── index.js │ │ ├── old.js │ │ └── package.json │ ├── glob │ │ ├── LICENSE │ │ ├── README.md │ │ ├── common.js │ │ ├── glob.js │ │ ├── package.json │ │ └── sync.js │ ├── inflight │ │ ├── LICENSE │ │ ├── README.md │ │ ├── inflight.js │ │ └── package.json │ ├── inherits │ │ ├── LICENSE │ │ ├── README.md │ │ ├── inherits.js │ │ ├── inherits_browser.js │ │ └── package.json │ ├── minimatch │ │ ├── LICENSE │ │ ├── README.md │ │ ├── minimatch.js │ │ └── package.json │ ├── once │ │ ├── LICENSE │ │ ├── README.md │ │ ├── once.js │ │ └── package.json │ ├── path-is-absolute │ │ ├── index.js │ │ ├── license │ │ ├── package.json │ │ └── readme.md │ ├── rimraf │ │ ├── LICENSE │ │ ├── README.md │ │ ├── bin.js │ │ ├── package.json │ │ └── rimraf.js │ └── wrappy │ ├── LICENSE │ ├── README.md │ ├── package.json │ └── wrappy.js ├── package-lock.json └── package.json
以上の結果より、コマンドが実行された順番でワークスペースルートにインストールされることを確認できた。
npm installの実行順について
下記のような状態で
app-a/package.json
... "dependencies": { "rimraf": "3.0.2" }, ...
app-b/package.json
... "dependencies": { "rimraf": "2.7.1" }, ...
- node_modulesとpackage-lock.jsonを削除してnpm iしたところAと同じ構造になることを確認
- package.jsonのworkspaceの順序を入れ替えてnpm iしてもAと同じ構造になることを確認
package.json
"workspaces": [ "app-b", "app-a" ]
- app-bの名前を変えてnpm iを実行すると、ワークスペースルートにrimraf@2.7.1がインストールされることを確認
%mv app-b app
% npm i
よってnpm iの実行順序はディレクトリ名順で実行されることがわかった。
まとめ
npm workspaceとnpm installの挙動について初めて見たときよくわからなかったのでまとめた。