先月、有名なnpmパッケージがマルウェアに汚染されるという出来事があった。
npm debug and chalk packages compromised
今までにもnpmパッケージの汚染は度々起こっていたらしいが、今回は20億ダウンロードを誇るパッケージで起こったということもあり、事情に疎い私もこの騒動を知ったのだった。
SNSを見ていると「npm installするのも怖い…」「npm installする前にチェックする方法はないのか」といった意見が見られた。その中でpnpmに事前チェック機能があるらしいことを知ったので、安全面を考えてnpmからpnpmに移行することにした。
pnpmとは
Node.jsのパッケージマネージャーで、“Performant npm”の略。“Performant”からも分かるように、パッケージインストールが高速でディスク容量が節約できて効率的なのが特徴である。
Fast, disk space efficient package manager | pnpm
npmが各プロジェクトごとにnode_moduleディレクトリにインストールするのに対し、pnpmはグローバルに一度インストールしたものをプロジェクトで共有する形をとる。各プロジェクト内のnode_moduleはシンボリックリンクが配置される。
npmからの移行手順
環境
ローカルPC:Windows11
- Node.js:v22.20.0
- Volta:1.1.1
ホスティング:Cloudflare Pages
- Framework preset: None
- Build command:
npm run build
pnpmのインストール
以下のVoltaコマンドでpnpmをインストールする
volta install pnpm
node_moduleフォルダを削除
既存のnode_moduleフォルダを削除する。
rm -rf node_modules
package.jsonに追加
プロジェクトで使用するパッケージマネージャーを pnpm に限定するための設定を追加する。package.jsonのscriptsの項目に以下を記述する。
{
...
"scripts": {
"preinstall": "npx only-allow pnpm",
...
}
}
パッケージを移行する
既存のパッケージをpnpmへ移行する。
pnpm import
このコマンドにより、既存のロックファイル(npmの場合はpackage-lock.json)を読み込み、pnpmのロックファイルpnpm-lock.yamlが作成される。
package-lock.jsonの削除
不要になったpackage-lock.jsonファイルを削除
rm package-lock.json
パッケージをインストール
pnpm install
すると、以下のような警告が出た。

pnpm10以降には、デフォルトでプログラムの自動実行をブロックする機能がある。悪意のあるパッケージがインストールされるリスクを防ぐためである。
esbuild(JavaScriptビルドツール)とsharp(画像処理ライブラリ)は信頼性の高いパッケージなので、実行を許可しても問題はない。メッセージ通りにコマンドを実行する。
pnpm approve-builds
pnpm-workspace.yamlファイルが作成され、以下のような記述がされる。
ignoredBuiltDependencies:
- esbuild
- sharp
「ビルドの依存関係を無視する」とは…? Google検索で出てこなかったのでChatGPT君(無料版)に訊いた。
ignoredBuiltDependencies は「特定の依存パッケージをインストール時のビルド対象から除外する設定」で、「ネイティブ依存の不要なビルドを避けて、インストールを軽量化・安定化する」のだそうだ(ITリテラシーが低いので、フワッとしか理解しかできていない)。
node_moduleフォルダ内を見ると、以下のようになっている。

npmのときは一体何に使っているのかというくらいたくさんのフォルダがあったが、pnpmはフォルダ数が少なく、矢印でグローバルを参照している(シンボリックリンク)。
pnpmのコマンド
npmと互換性が高く、大抵の操作はnpmをpnpmに置き換えて行うことができる。
# npm
npm instal package-name
# pnpm
pnpn instal package-name
やっておいたほうがよい設定
pnpm10以降には、デフォルトでプログラムの自動実行をブロックする機能があるが、更にセキュリティを強化しておきたい。
pnpm 10.16から、パッケージ公開から最低限の日数が経過するまでインストール対象外にするオプションが追加された。マルウェアに汚染されたパッケージは、基本的にパッケージ公開後1日以内に発見されて駆除される。なので、更新から一定期間経過したパッケージのみインストールするよう設定しておけば、リスクを軽減できるということである。
グローバルに設定
pnpm config set minimumReleaseAge 1440
グローバル設定ファイルは、Windows11の場合C:\Users\PC_User\AppData\Local\pnpm\config\rcにある。設定できたかどうかはpnpm config listで確認できる。
プロジェクトのpnpm-workspace.yamlに記述
minimumReleaseAge: 1440
Cloudflare Pagesの設定
npmからpnpmに変更になったことで、Cloudflare Pagesの設定も変更しなければならないかと思ったが、普通にビルドできた。package.jsonは"preinstall"の項目を追加した以外は変更していない。
pnpmに換えれば必ずしも安全というわけではないが、npmで無防備でいる頃よりもセキュリティが高まったのではないかと思う。
おまけ

Astroをインストールするコマンドが記述されている箇所だが、2番目のpnpmがアクティブになっている。
npmを1番目にして立てつつ、pnpmを推しているような印象(※個人の感想です)。