以下の内容はhttps://let.blog.jp/tag/npmより取得しました。


依存パッケージの数を知りたい
◯ Yarn v1 の場合

yarn.lock のトップレベルキーの数
コメントの # 行は無視

const lines = fs.readFileSync("./yarn.lock").toString()
.split("\n")
.filter(x => x[0]?.trim() && x[0] !== "#")

console.log(lines.length)
console.log(lines.join("\n"))
42
accepts@^1.3.5:
cache-content-type@^1.0.0:
co@^4.6.0:
content-disposition@~0.5.2:
content-type@^1.0.4:
cookies@~0.9.0:
debug@^4.3.2:
deep-equal@~1.0.1:
delegates@^1.0.0:
depd@^2.0.0, depd@~2.0.0:
depd@~1.1.2:
...

◯ Yarn Berry

2 以降でも基本は同じ
だけど yarn.lock ファイルが YAML として有効なファイルになってるので YAML としてパースしてトップレベルキーの数を数える方法も取れる

2 以降の yarn.lock では自身もエントリとして存在する
「foo@workspace」 みたいなの
さらに __metadata という特殊なキーもあるので これらを除外する必要あり

const data = require("yaml").parse(fs.readFileSync("./yarn.lock").toString())

console.log(Object.keys(data).length - 2)
console.log(Object.keys(data).join("\n"))
42
"accepts@npm:^1.3.5":
"cache-content-type@npm:^1.0.0":
"co@npm:^4.6.0":
"content-disposition@npm:~0.5.2":
"content-type@npm:^1.0.4":
"cookies@npm:~0.9.0":
"debug@npm:^4.3.2":
"deep-equal@npm:~1.0.1":
"delegates@npm:^1.0.0":
"depd@npm:^2.0.0, depd@npm:~2.0.0":
"depd@npm:~1.1.2":
...

YAML ライブラリを入れなくても v1 と同じように行ごとの単純処理でも十分対応できる
YAML として有効なファイルになったことでキーは必ず 「"」 から始まってる
1 文字目が 「"」 という単純なカウントで済むので v1 より楽
この方法だと __metadata は含まれないので 自身のパッケージの数だけ除外すればいい

const lines = fs.readFileSync("./yarn.lock").toString()
.split("\n")
.filter(x => x[0] === '"')

console.log(lines.length - 1)
console.log(lines.join("\n"))
42
"accepts@npm:^1.3.5":
"cache-content-type@npm:^1.0.0":
"co@npm:^4.6.0":
"content-disposition@npm:~0.5.2":
"content-type@npm:^1.0.4":
"cookies@npm:~0.9.0":
"debug@npm:^4.3.2":
"deep-equal@npm:~1.0.1":
"delegates@npm:^1.0.0":
"depd@npm:^2.0.0, depd@npm:~2.0.0":
"depd@npm:~1.1.2":
...

Yarn Berry でゼロインストールにしてる場合は .yarn/cache にパッケージの zip ファイル一覧が並ぶのでこれを数えることもできる
.yarnrc.yml で enableGlobalCache: false になってると .yarn/cache にパッケージファイルが保存されてる
node_modules と違ってネストされないので同じ階層のファイル数で判断できる

ls .yarn/cache/ | wc -l
42

ここの方法だと自身は含まれないし __metadata キーもないので一番楽
一応 .gitignore が cache フォルダにあるけど隠しファイルなので ls に出てこない

◯ npm

package-lock.json の packages オブジェクトのキーの数
lock ファイルが JSON なので一番カンタンかも

トップレベルの packages プロパティにオブジェクトが入っていて このオブジェクトのキーがパッケージ一覧になってる
Yarn Berry 同様で自身(キーは 「""」)が含まれてるので それの除外が必要

const data = require("./package-lock.json")

console.log(Object.keys(data.packages).length - 1)
console.log(Object.keys(data.packages).join("\n"))
42
node_modules/accepts
node_modules/cache-content-type
node_modules/co
node_modules/content-disposition
node_modules/content-type
node_modules/cookies
node_modules/debug
node_modules/deep-equal
node_modules/delegates
node_modules/depd
...

◯ pnpm

pnpm-lock.yaml ファイルの packages オブジェクトのキーの数
npm に近いけど YAML なのでパースが面倒
単純な方法でやるなら 「  /」 から始まる行の数

const data = require("yaml").parse(fs.readFileSync("./pnpm-lock.yaml").toString())

console.log(Object.keys(data.packages).length - 1)
console.log(Object.keys(data.packages).join("\n"))
42
/accepts@1.3.8
/cache-content-type@1.0.1
/co@4.6.0
/content-disposition@0.5.4
/content-type@1.0.5
/cookies@0.9.1
/debug@4.3.4
/deep-equal@1.0.1
/delegates@1.0.0
/depd@1.1.2
/depd@2.0.0
/destroy@1.2.0
npm run で npm が出す出力を消したい
JSON 形式でログを出力するスクリプトがあります

const log = (v) => console.log(JSON.stringify(v))

log({ value: 1 })
log({ value: 2 })

yarn berry で yarn start で実行すると

[root@60303402bf2f tmp]# yarn start
{"value":1}
{"value":2}

余分な出力がありません

しかし npm に置き換えると

[root@60303402bf2f tmp]# npm run start

> tmp@1.0.0 start
> node x.js

{"value":1}
{"value":2}

パッケージ名や 実行されるコマンドが出力されます
デバッグ時にはいいのですが 本番実行時に JSON 以外がログに混ざるのは避けたいので出力してほしくないです

--silent (-s) で消せるようです

[root@60303402bf2f tmp]# npm run start -s
{"value":1}
{"value":2}

この辺も yarn のほうが使いやすいなと思いましたが yarn v1 だとバージョンなどもっと色々出てました

[root@60303402bf2f tmp]# yarn run start
yarn run v1.22.22
$ node x.js
{"value":1}
{"value":2}
Done in 0.11s.

ウェブサーバーなど常駐プロセスの起動ならいらないですが CLI ツールとして使うなら実行時間が表示されるのは少し嬉しいかもしれません
npm run で command というコマンドを実行できない
package.json に

{
....
"scripts": {
"c1": "command1"
},
....
}

と書けば 「npm run c1」 で command1 というコマンドを実行できます
この command1 に当たるコマンドは通常 npm などでインストールしたパッケージに含まれるコマンドです

推奨される方法ではないですが 直接 node_modules フォルダ内に .bin/command1 というファイルを配置すれば実行できます

#!/usr/bin/env node

console.log(123)

という中身にします

Windows の場合は command1.cmd のように cmd 拡張子をつけて 中身は cmd ファイル (bat ファイル) にします
.js ファイルを実行するなら node コマンドを呼び出します

Linux の場合はファイルの実行権限が必要なので chmod で追加します

これで 「npm run c1」 を実行すると

root@abc0c5fc3c92:/mnt/88# npm run c1

> 88@1.0.0 c1
> command1

123

のように実行されます

ここで command1 は存在してパスの通っているコマンドやシェルのビルトインと同名でも大丈夫です
例えば

{
....
"scripts": {
"c1": "ls"
},
....
}

として node_modules/.bin/ls にファイルをおけば この ls が実行されます
ファイルの一覧が表示されたりはしません
しかし command というコマンドにした場合 なぜかシェルビルトインが優先されるような動きで node_modules/.bin/command が使用されないです

root@abc0c5fc3c92:/mnt/88# npm run c1

> 88@1.0.0 c1
> ls

123

root@abc0c5fc3c92:/mnt/88# npm run c1

> 88@1.0.0 c1
> command

123 が表示されていません
npm でも yarn でも同じ結果です
Windows では command.cmd を実行するからか問題ないです
たぶん Linux 側の仕様によるものな気がしますが これにハマって時間をとられました
Wireit 思ってたのと違ってそう
OSS の package.json を見てると wireit というキーがあるのを見つけました
なにかと思って調べたら Google 製のツールで npm run を拡張してくれるものみたいです
https://github.com/google/wireit

便利そうなものかなと期待して詳しい機能を見ていたのですが 思ってたのと違ってそうでした
コマンド間に依存関係を定義できて 依存するコマンドも自動で実行してくれたり 並列に実行したりとかそういうのがメインみたいです

またインクリメンタルビルドやキャッシュやウォッチ機能があり そのために各コマンドの入力と出力のファイルを書かないといけないようです
たしかにこういった機能の実現だと必要そうですが これが結構面倒そうです
それに各コマンド側でもすでに持ってる情報なので二重に管理することになり 漏れが出そうですし

また環境変数を設定できるようですが静的な値のみのようです
求めてるのはコマンド実行時に OS 依存せず指定できることなので求めてることはできなさそうです
こういうのがやりたいのです

期待してたのとは違ったので私は使わなそうです
Github アクションとの統合もあるようですし OSS 向けなんでしょうかね
unpkg などの CDN の依存解決は実行時のバージョンになる
unpkg などの CDN を使うとき バージョンを指定しなければ最新版が使われます
それだと後々動かなくなるかもしれないのでバージョンを固定するために バージョン付きの URL にします
これで大丈夫だろうとは思っていましたが ダメでした

依存モジュールがある場合は 別の URL をインポートすることになりますが それが別のパッケージの場合は package.json のように ^2.4.0 みたいな指定になります
この指定だと互換性がある中での最新版となり 実行するタイミングによってバージョンが変わります
依存パッケージのバージョンは固定できません

通常は互換性があるバージョンなので問題ないはずですが 完全にそうとはいかないです
バグが入り込むケースもあれば マイナーバージョンのアップデートなのに breaking change を起こしているパッケージもあります
そういうことがあるので yarn.lock などの lock ファイルがあり 依存パッケージのバージョンまで固定しているわけです

CDN が最初のアクセス時点で依存パッケージも含めバンドルしてしまい 同じ URL なら依存パッケージも含めて同じになるようにしてくれるといいのですが それだと依存パッケージに修正が入ってもそれが反映されないとかの問題が出そうです
?key=abcd みたいなクエリをつけて key ごとに初回アクセス時にバンドルしてくれれば 更新したいタイミングで key を変えて対応できそうですが多数の key 違いの URL でアクセスされると CDN 側で保持するバンドル数が多すぎて現実的でないです

依存関係も含めて完全に動作確認済みのバージョンで動作させたいのなら CDN は避けたほうがいいのかもですね
ただ Deno って基本は URL 指定なので同じ問題が起きそうな気がします
ローカルにキャッシュされるので同じ環境だと問題ないですが 別環境だとその時点の最新になるはずです
キャッシュの共有が必要になってくるとそれも面倒です

この辺はどうするのがいいのでしょうね
npm のローカルパッケージ参照機能が yarn より使えない
yarn は file: と link: で扱いを変えられる
file の場合はパッケージのフォルダを node_modules 内にコピーして link の場合はシンボリックリンクを作る
npm は file しかなくて file でシンボリックリンクが作られる
コピーはほぼ使わないから これだけだと npm でも問題ない

npm はリンクするパッケージ内の dependencies の扱いで問題が出る
リンク先がプロジェクト内のサブフォルダだと devDependencies も含めてインストールされる
プロジェクトのサブプロジェクトならテストなど開発用機能も使うだろうという判断?

実際には npm ライブラリをベースにバグ修正や自分用にカスタマイズで少しだけいじったものと置き換える使い方が多い
そういうときに devDependencies は要らない
だけどこれを除外する方法がなさそう
devDependencies を消して対処しかない?

workspace が使われてるパッケージだと devDependencies は workspace を前提にしていて単独だとインストールできない場合もある
production モードでインストールすれば devDependencies のインストールは回避できたと思うけど この方法だとメインの devDependencies も入らなくなってしまう
メインの devDependencies にはフォーマッターやテストなどの必要なものがあるのでインストールされないのは困る

またリンク先がプロジェクトフォルダの外だと動作が変わる
単にリンクされるだけで dependencies すらインストールされない
手動でリンク先で npm install コマンドを実行しろってことみたい
プロジェクト外なら複数箇所で共有されてるかもしれないからそのパッケージフォルダ内に node_modules を作って共有するというのもわからなくはないけど

ただ実際にはこれらの機能は使いづらいだけ
yarn ならプロジェクトの内外を気にせず リンクしたパッケージは他のパッケージと同じように扱われて dependencies のみインストールされる
これが求めてる挙動だけど npm だと同じことをする方法がなさそう

経験がないけど yarn の挙動だと問題が出る可能性はあるのかも
バージョン競合で node_modules 内のパッケージの中に node_modules がネストして作られることがある
そのときにリンクしたパッケージ内に部分的な node_modules ができて気持ち悪いことになる可能性があるのかも
1 箇所からの使用なら別にも気にしなければいいだけだけど 複数箇所からリンクしてると部分的な node_modules は問題になる可能性も?
SheetJS が npm から独自 CDN に移行するみたい
https://www.bleepingcomputer.com/news/software/npm-package-with-14m-weekly-downloads-ditches-npmjscom-for-own-cdn/

おすすめにこんなページが出てきました
タイトルを見てまた npm で何かあったのかと思ったら SheetJS が npm での公開をやめるみたい
理由は Github で 2 段階認証が強制されたことや別の問題もあるみたい
npm と SheetJS 間で訴訟があったみたいだけどここでは説明しないって書かれてるので詳しくはわからない
Github に issue ができてピン止めされてた
https://github.com/SheetJS/sheetjs/issues/2667

2 段階認証は自分も嫌いで強制されるのは嫌なのでわからなくもない

SheetJS って名前には聞き覚えあるし JavaScript で Excel 操作するライブラリは過去に何かで使ってたから今後対応必要になるのかもと思って調べたらこのサイトみたい
https://sheetjs.com/

たしかここって有料(?)の Pro プランがあるところで 機能は揃ってるけどスタイルかなにかを変更する機能を使うには Pro 版が必要になって無料版だとちょっとしたことをするのにも使えなかったやつだったような……
ググって出てきたそれっぽい QA
https://stackoverflow.com/questions/50110595/how-to-add-cell-border-to-sheetjs-xlsx-generated-file

それならこのパッケージは使ってなかった気がするし npm やめても別に困らないかな
npm の Github に join が完了した
https://github.blog/2020-04-15-npm-has-joined-github/

以前もニュースになってましたが 完了したみたいですね

それにしても Github も npm もマイクロソフトですかー
以前はマイクロソフトは IE と Bing のせいで Web はダメなイメージだったのですが
最近では TypeScript や VSCode もありますし それに加えて Github と npm
いつのまにか Web の開発関係はほぼマイクロソフトツールになりつつありますねー
AWS や GCP に比べるとマイナー感ありますが Azure もやってますし

Web といえば Google のイメージでしたが Google の大きなサービスだと
検索 / Chrome / 地図 / Youtube / 翻訳 などです
開発者的には関係が強いのはやっぱり Chrome です
しかしそれも Edge が Chromium ベースになったのでマイクロソフトも開発に参加してます

一般のウェブユーザが直接関わるものだとやっぱり Google のほうが多そうですが
開発者向けだとマイクロソフトのほうが多いですね
その勢いで IE もどうにかしてほしいものですけど
npm のバージョンリストに日付を表示する
npm の Version History のところは相対日付しか表示されていなくて 2 years ago とかが並んでてもあまり嬉しくないです
具体的にいつ頃なのかわからないですし このバージョンとこのバージョンの間はどれくらい空いてたのかを知りたい時とか不便すぎです

一応マウスを乗せるとツールチップで表示されますが ひとつひとつ乗せないとダメなのは面倒です
同時に見れないですし

そこで title 属性(ツールチップのテキスト)を表示するような CSS を用意しました

time:before {
content: attr(title);
color: #d0841e;
font-size: 11px;
margin-right: 20px;
}

このスタイルを npm のページで表示するようにすれば相対日付の左側に完全な日付が表示されます
Nodist で npm をインストールできない
npm で使おうとした機能が使えなくて npm バージョンを見たら 4
最新は 6.13 だから結構古め

せっかくだから Noidst も一緒にアップデートして Nodist を今の最新の 0.9.1 にした
それから npm をインストールしようとしたら インストールできない

ダウンロードのプログレスバーが途中のところで進まなくなって その後中断される
エラーとかのメッセージは何もなし
バージョンのフォルダは作られてるけど中身が空っぽの状態
実行するファイルがないので 「npm --version」 とか実行してもエラーになる

Chrome で直接ダウンロードするファイルをダウンロードしてみたら普通にダウンロードできた
なんなんだろう?
バグ?

Nodist は独自の管理データは持ってなくて直接フォルダをみてるだけみたいなので とりあえず自分でダウンロードした npm を直接フォルダに配置すれば普通に使えた
配置する場所は

C:\Program Files (x86)\Nodist\npmv

ここにバージョン名のフォルダを作って中にダウンロードした tar.gz を解凍した中身をいれる
npm をダウンロードする場所は 6.13.1 だとここ

https://codeload.github.com/npm/cli/tar.gz/v6.13.1
uws が消された
ちょうど消された頃に知ったのですが忘れてたので short の方に

WebSocket ライブラリの socket.io のソースをみていたら ws という別の WebSocket ライブラリを発見
engine.io が WebSocket のコア部分のライブラリかと思ったら engine.io が中で ws を使ってるみたい

socket.io って結局 ws のラッパー?
よく見ると ws 以外にも uws というのがあって switch 文でどっちを使うか切り替えてる

https://github.com/socketio/engine.io/blob/master/lib/server.js#L108

調べてみたら C++ で書かれた速度重視版で ws と基本的互換性があるとか
npm をみたら deprecated になってた
https://www.npmjs.com/package/uws

見つけたときはちょうどなったばかりで 99.0.0 というバージョンもあって どうなってるんだろう?と思って調べてたらこんなページが

https://www.reddit.com/r/node/comments/91kgte/uws_has_been_deprecated/

Google 翻訳で軽くみた感じでは 作者が npm の考えに賛同できなくてパッケージの公開をやめたみたい
問題のあるバージョンでも消すことができないというのが嫌だったとか
マイナーバージョンアップの 10.148.2 で中身が空のパッケージをリリースしたせいで確認せずアップデートして一部ではトラブルにもなったみたい

使ったこと無いパッケージだったけどこんな事が起きてたんですねー
npm install での package.json への書き込み
--save というのはない
ヘルプに載ってないし古い書き方?

使えるのは

--save-prod (-P)
--save-dev (-D)
--save-optional (-O)
--no-save

save-prod は 「dependencies」
save-dev は 「devDependencies」
save-optional は 「optionalDependencies」
に追加される

no-save は package.json に書き込みしない

指定しないと save-prod 扱いで dependencies に追加される
dependencies はパッケージを実行するときに必要なもの
ライブラリとかフレームワークとか

devDependencies は開発時に必要なもの
テストとかデバッグ用のツールとか

バージョン指定はその時の最新版と互換性あるものとして 「^4.0.0」 みたいな表記になる
正確にその時インストールしたバージョンを保存するには --save-exact (-E) をつける



以上の内容はhttps://let.blog.jp/tag/npmより取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14