npmの個人メモ
フロントエンドを開発するときに絶対にでてくるnpm。
ちゃんとキャッチアップしたことがなかったので、ググってよく見られてそうな以下の記事を読みます。
Node.jsを使用するうえでnpmはちゃんと理解しておいた方がいいです。
とのこと。はい。理解します。
npmとは
- Node.jsのパッケージを管理するシステム
パッケージとは
- モジュールとは
- 他のプログラムから利用することを目的としたクラスや関数などのプログラム
- パッケージとは
- モジュールをまとめて機能するようにしたもの
- ライブラリとも呼ばれる
- npmの独自定義
- npmに存在するのはパッケージとモジュール
npmの必要性
- 以下の問題を解決するためにnpmが必要
- パッケージの依存関係
- パッケージの競合関係
- パッケージxで使用しているパッケージyが新しくインストールするパッケージzでも使われているとか
Yarn
- npmよりもインストールが速く、セキュリティが高い特徴がある
- npmと互換性があるパッケージ管理システム
- 筆者は改善されてきたnpmで十分かな、らしい
npmのインストール
- Node.jsをインストールすると同時にインストールされる
- Node.jsにはnvm(Node Version Manager)というNode.jsのバージョン管理システムで管理できる
- Node.jsは頻繁にバージョンアップされるからできるだけnvmを入れよう
Linux
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash # bashを開き直す $ tail -n 3 ~/.bashrc export NVM_DIR="$HOME/.config/nvm" [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion # nvmのバージョン $ nvm --version 0.39.1
使い方
# nodejsのインストール $ nvm install 16.13.2 # インストールされているバージョンの一覧 $ nvm list -> v16.14.1 system default -> 16.14.1 (-> v16.14.1) iojs -> N/A (default) unstable -> N/A (default) node -> stable (-> v16.14.1) (default) stable -> 16.14 (-> v16.14.1) (default) lts/* -> lts/gallium (-> v16.14.1) lts/argon -> v4.9.1 (-> N/A) lts/boron -> v6.17.1 (-> N/A) lts/carbon -> v8.17.0 (-> N/A) lts/dubnium -> v10.24.1 (-> N/A) lts/erbium -> v12.22.10 (-> N/A) lts/fermium -> v14.19.0 (-> N/A) lts/gallium -> v16.14.1 # galiiumだけインストールされてるってことかな。 # リストアップされているのはLTSバージョンかな。 # バージョン切り替え $ nvm use 16.14.1 # アンインストール $ nvm uninstall 16.14.1 # nvmバージョン $ nvm --version # 利用しているnodeのバージョン? $ nvm version
npmの使い方
プロジェクトの作成
- npmはプロジェクト内でパッケージを管理するものなのでプロジェクトを作成する必要がある
初期化
npm init
でpackage.jsonを作成する- package.jsonを作成しないでもパッケージのインストールはできる
- ただしnpm管理にならないので恩恵にあずかれない
- 依存関係の管理ができないってことかな
- ただしnpm管理にならないので恩恵にあずかれない
- package.jsonが無いところで、
npm install xxx
したらインストールできた
# initで初期化(package.jsonを作成) # -y つけると全部初期値で作成 $ npm init -y Wrote to /home/xxxxx/npm_sample/package.json: { "name": "npm_sample", // パッケージの名前 "version": "1.0.0", "description": "", // npmリポジトリの説明欄 "main": "index.js", // メインファイル(一番最初に実行されるファイル) "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], // パッケージを公開したときの検索ワード "author": "", "license": "ISC" }
proxy
- proxyをかましたい場合に設定可能
# 設定の確認 $ npm config list ; node bin location = /home/xxxx/.config/nvm/versions/node/v16.14.1/bin/node ; cwd = /home/xxxx/npm_sample ; HOME = /home/xxxx ; Run `npm config ls -l` to show all defaults. # 詳細情報 $ npm config ls -l # configのset $ npm config set proxy [proxy url]
インストール
# ローカルインストール(install -> iでもよい) $ npm install typescript ⸨⠂⠂⠂⠂⠂⠂⠂⠂⠂⠂⠂⠂⠂⠂⠂⠂⠂⠂⸩ ⠴ idealTree:npm_sample: sill idealTree buildDeps added 1 package, and audited 2 packages in 24s found 0 vulnerabilities # バージョン指定のインストール # vueの最新は3.xだが、2.6.xを入れたい場合 $ npm info vue vue@3.2.31 | MIT | deps: 5 | versions: 370 # ...省略 dist-tags: csp: 1.0.28-csp latest: 3.2.31 legacy: 2.6.14 next: 3.2.31 # 2.6.14がlegacyらしい $ npm i vue@2.6.14 added 1 package, and audited 3 packages in 2s found 0 vulnerabilities $ cat package.json # 抜粋。vue2.6.14がインストールできた # --saveしなくてもdepencenciesに追加されるのね "dependencies": { "typescript": "^4.6.2", "vue": "^2.6.14" } # devDependenciesへの追加 # --save-dev または -D $ npm i -D webpack $ cat package.json # 抜粋。webpakがdevの方に追加された。 "devDependencies": { "webpack": "^5.70.0" }
package.jsonに設定されたパッケージのインストール
$ cd [ package.jsonがあるディレクトリ] $ npm install
npmのバージョンアップ
npm自信をグローバルインストールする
$ npm install -g npm
不思議だな。
パッケージ一覧
# 直接インストールしたもの npm list --depth=0と同じ # インストールしたパッケージが依存しているパッケージは表示されない $ npm list # 表示形式が違うバリエーションがある $ npm ls $ npm la $ npm ll # パッケージが依存しているパッケージも表示 $ npm list --depth=1 npm_sample@ /home/xxxx/npm_sample ├── typescript@4.6.2 ├── vue@2.6.13 └─┬ webpack@5.70.0 ├── @types/eslint-scope@3.7.3 ├── @types/estree@0.0.51 ├── @webassemblyjs/ast@1.11.1 ├── @webassemblyjs/wasm-edit@1.11.1 ... # グローバルインストールパッケージ一覧 $ npm list -g
パッケージ情報の検索/取得
# npmリポジトリから検索 $ npm search vue NAME | DESCRIPTION | AUTHOR | DATE | VERSION | KEYWORDS vue | The progressive… | =yyx990803… | 2022-02-12 | 3.2.31 | vue # パッケージ詳細情報の表示(info -> view or showのエイリアスあるどれも同じ) $ npm info vue # パッケージの最新バージョン $ npm info vue version 3.2.31 # インストール可能なパッケージ一覧 $ npm info vue versions [ '0.0.0', '0.6.0', '0.7.0', '0.7.1', '0.7.3', '0.7.4', ...
パッケージのアップデート
# アップデートの確認 $ npm outdated Package Current Wanted Latest Location Depended by @vue/cli 5.0.2 5.0.3 5.0.3 node_modules/@vue/cli npm_sample vue 2.6.14 2.6.14 3.2.31 node_modules/vue npm_sample # 多分wantedにあげた方がよい。vueのLatestはメジャーバージョンが上がって破壊的な変更が入っているので、wantedと一致してない # アップデート $ npm update @vue/cli # パッケージ名省略で全部アップデート $ npm update # npm updateで@vue/cliだけアップデートされた。wantedまで上がるということか $ npm outdated Package Current Wanted Latest Location Depended by vue 2.6.14 2.6.14 3.2.31 node_modules/vue npm_sample # でもpakcage.jsonに反映されないな。自動反映されないのか? $ cat package.json { "dependencies": { "vue": "^2.6.13" }, "devDependencies": { "@vue/cli": "^5.0.2", "typescript": "^4.6.2" } } # ^5.0.2 は5.0.3を含むから、別に更新しなくていいのか。
npm-check-updates
- 複数のパッケージのアップデータを便利できる
$ npm i -g npm-check-updates $ ncu Checking /home/xxxxx/npm_sample/package.json [====================] 3/3 100% vue ^2.6.13 → ^3.2.31 @vue/cli ^5.0.2 → ^5.0.3 # vue/cliの5.0.3はインストールされているはずだけどpackage.jsonベースの確認 # package.jsonへの反映 $ ncu -u Upgrading /home/xxxxx/npm_sample/package.json [====================] 3/3 100% vue ^2.6.13 → ^3.2.31 @vue/cli ^5.0.2 → ^5.0.3 Run npm install to install new versions. # vueと@vue/cliがバーアップされてしまった。 $ cat package.json { "dependencies": { "vue": "^3.2.31" }, "devDependencies": { "@vue/cli": "^5.0.3", "typescript": "^4.6.2" } } # vueは除外したいな $ ncu -u -x vue Upgrading /home/xxxx/npm_sample/package.json [====================] 2/2 100% @vue/cli ^5.0.2 → ^5.0.3 # ncu のパッケージ指定は正規表現も使える
ncuは以下で確認
アンインストール
# uninstallじゃなくて、remove, rm, r, un, unlink でも同じ $ npm uninstall @vue/cli $ npm uninstall -g @vue/cli # グローバル # package.jsonへの反映 # 試してみると、--saveを指定しなくてもpackage.jsonに反映される # npmのバージョンの問題かな $ npm un --save @vue/cli
ローカルインストールの罠
PATHを通す。
# グローバルインストールの場所 $ npm root -g /home/xxxx/.config/nvm/versions/node/v16.14.1/lib/node_modules # パッケージを探す探索パスは以下でも確認可能 # nodejsのグローバル変数を出力している # node -e でワンライナーを実行できるのね $ node -e "console.log(global.module.paths)" [ '/home/xxxx/npm_sample/node_modules', '/home/xxxx/node_modules', '/home/node_modules', '/node_modules' ] # 上から順にモジュールを検索するのか。一つ目はローカルだな。 # npmコマンドのインストール先 # グローバル $ npm bin -g /home/xxxx/.config/nvm/versions/node/v16.14.1/bin # ローカル。ローカルパッケージディレクトリにて $ npm bin /home/xxxx/npm_sample/node_modules/.bin # 以下にパスを通すとglobal.module.pathsに反映される $ export NODE_PATH=<PATH>
ローカルパッケージの実行
# ./node_modules/.bin への絶対パスを返す $ npm bin tsc /home/xxxx/npm_sample/node_modules/.bin $ ll ./node_modules/.bin/ lrwxrwxrwx 1 xxxx xxx 21 Mar 19 13:40 tsc -> ../typescript/bin/tsc lrwxrwxrwx 1 xxxx xxx 22 Mar 19 13:48 vue -> ../@vue/cli/bin/vue.js # .binには各node_modules以下のコマンドへのシンボリックリンクがある # 直接.bin以下を叩いてもよいが面倒なので、npxがあるよってのがこのあとの話
npx
./node_modules/.bin
からコマンドを探して実行してくれる- コマンドがインストールされてなくても探して実行してくれる
- え?npm installしてなくてもってことかな
$ npx webpack Need to install the following packages: webpack Ok to proceed? (y) y # インストールを求められるだけだな、npmのバージョンで違いがあるのかな # ローカルインストールされてれば以下のように実行可能 $ npx tsc -V Version 4.6.2 # urlからもnpxやnpm installできる? $ npx https://github.com/Microsoft/TypeScript.git npm ERR! could not determine executable to run # エラーになった。別のパッケージならできるのかな。 $ npm install https://github.com/Microsoft/TypeScript.git ⸨#########⠂⠂⠂⠂⠂⠂⠂⠂⠂⸩ ⠸ reify:typescript: sill audit bulk request { typescript: [ ' # なんか時間かかるので止めた
npxやnpm installでURLを指定するのは、あまり一般的ではないのかな。便利に使えるケースもあまり無い気もするし。公開されてない社内レポジトリのパッケージを使うとき、とかかしら。
package.json
- package.jsonとはプロジェクトの構成、構造を示した設計書のようなもの
- プロジェクト=パッケージ
name
- パッケージの名前
@
と/
の間にユーザーネーム(or組織名)をいれて名前空間とするscoped packages形式のネーミングも多い
version
- 決まりは無いが、大抵はセマンティックバージョニングに則ってる
description
- パッケージの説明、
npm search
で表示される
private
- パッケージを公開しない設定
- 開発時は「true」にした方が良い
main
- そのパッケージをインストールする際に開始となるファイル
bin
$ ll ./node_modules/.bin/ | grep tsc lrwxrwxrwx 1 xxxx xxxx 21 Mar 19 13:40 tsc -> ../typescript/bin/tsc $ cat ./node_modules/typescript/package.json | grep bin "bin": { "tsc": "./bin/tsc", "tsserver": "./bin/tsserver"
scripts
- コマンドのエイリアス
npm run xxxx
で実行- 慣習的に使われるエイリアスがある
- start: プログラムを実行する
- test : テストを実行する
- 名前の先頭に
pre
をつけるとついてないコマンドを実行する前にpre
がついたコマンドが実行されるpost
もある- preとかpostとかあまり使われてなさそう。見かけない。
dependencies
npm insall vue --save
でpackage.jsonのdependenciesに追記される- ローカル環境だと
--save
つけなくても追記される
- ローカル環境だと
npm 5.0.0
からのデフォルトの挙動らしい.自分のローカルは「8.5.0」、「5.0.0」が出たのはもう5年前らしい。
qiita.com
package-lock.json
もなんか最新バージョンと違うきもするが、あとで調べよう。
- dependenciesのバージョンに指定されている文字
^
: メジャーバージョンを固定(マイナー、パッチはあがる)~
:メジャー、マイナーバージョンを固定(パッチはあがる)- なし:全部一致
devDependencies
--save-dev
か-D
をつける- 開発やテスト時につかうパッケージを設定する
optionalDependencies
- インストールに失敗しても、他のインストールの処理が続行される
- なくても問題ないパッケージ
- あまり設定することない
- いつ設定するんだろうか
package-lock.json
- パッケージのバージョンをロックするファイル
- npm installで作成される
- npm installでインストールするたびに更新される?
- npm 8x だとそうでもないような挙動に見える、バージョン差分かな
- 複数人で開発するときにバージョンをあわせられる
- git管理する
- 人の手では更新しない
npm update
で更新される。(package.jsonは更新されないようだ)
- pakage-lock.jsonでインストールするには、
npm insltall
ではなくてnpm ci
を利用する?- npm 8xでは
npm install
でもpackage-lock.jsonを見てそうだった
- npm 8xでは
パッケージとモジュール
- npmでのモジュールとは
- npmのパッケージとは
まとめ
- 最初は全てパッケージ
- パッケージを他のパッケージインストールして、その使われ方によってパッケージとモジュールにわかれる
- 単体で使用するならパッケージ。読み込まれて使用されるならモジュール。
なんとなくわかったが。。JSでimport or requireされるJSはモジュールになる、ということかな。(基本はパッケージ)
パッケージの公開
- パッケージは以下からダウンロードしている
- npm installで通信している先
- 誰でもパッケージを登録することが可能
- アカウント作成が必要
- 削除したパッケージ名+バージョンは2度と登録するこはできない
npm
はNode Package Manager
の略ではなくて、npm is Not An Acronym
らしい。- バクロニムと呼ばれるものらしい。
試してみたいけど、なにもできないソースあげてもなぁ。
$ npm login # npmサイトにログインする。アカウント必要。ワンタイムパスも。 $ npm publish # 公開 $ npm logout # ログアウトは忘れずに # アップデート # package.jsonのバージョンを更新 $ npm publish # ログインしてからね # 削除 $ npm unpublish パッケージ名