2026/05/08(金)npmからpnpmに切り替えた

投稿日:

今までNode.jsのパッケージ管理は標準であるnpmを使っていたが、脆弱性の指摘や、高速性の観点からpnpmに切り替えることにした。

Yarnはなんかいけ好かない感じだったが、pnpmはnpmとコマンドの互換性があり、打ち辛いことを除いては使いやすい。公式ではエイリアスの設定を推奨しているが、エイリアスを前提とすると運用が辛いのとpnと言われても何のことやらわからないので私はそのまま使っている。ただただ打ち辛い。

互換性のあったコマンド

確認した限り次のコマンドは互換性があったため、基本的にnpmの頭にpを生やしてpnpmとするだけで問題ないのが便利だ。

  • npm start
  • npm t
  • npm i
  • npm i <pkg名>
  • npm i -D <pkg名>
  • npm un <pkg名>
  • npm version minor
  • npm version patch
  • npm publish
  • npx
    • pnpxで同じことができる

pnpm公式によるとパッケージの追加はpnpm add <pkg名>ないしpnpm add -D <pkg名>の様だが、npmの互換性のためなのかaddでなくiでも機能するようになっている。打鍵回数が減るのでありがたい。

便利なところ

インストールが爆速。グローバルインストールにエイリアスを持っているので極めて速い。

npm runrunが不要になった。Yarnもそうだがrunなしでscriptを走らせることができる。便利だ。

パッケージのアップデートがpnpm upで一括でできるようになった。npmの時はnpm-check-updatesでpackage.jsonを更新したのちnpmを走らせる必要があり面倒だったが、これは便利だ。

セキュリティについて

セキュリティが強いらしいが、今のところ実感はない。

拙作の@lycolia/ts-boilerplate-generator-cliではグローバルインストール時に一回警告が出たがpnpm approve-builds -gというコマンドを叩いてパッケージを選択したら以後は出なくなった。恐らくpostinstall関連だと思われるが、よくわかっていない。

このコマンドを叩かないとパスが通らず実行できないようだったが、パッケージをアップデートしても再度は出なかったため、特別な設定をしない限り何かしらの攻撃を受ける可能性はありそうだなと思った。

やったこと

自分が使っているリポジトリでは以下の対応を行った。

  1. CIなどのスクリプト(シェルスクリプトやpackage.jsonscripts、GitHub Actions Workflow)にあるnpmpnpmに、npm run xxxとしている箇所をpnpm xxxに、npxpnpxに置き換えた
  2. GitHub ActionsのWorkflowでpnpmを使えるようにした
    1. actions/setup-nodeの手前にpnpm/action-setupを追加し、actions/setup-nodecacheの指定をpnpmpnpm-lock.yamlに変更
         steps:
      -      - uses: actions/setup-node@v6
      +      - uses: actions/checkout@v6
      +      - uses: pnpm/action-setup@v4
      +        with:
      +          version: 10
      +      - uses: actions/setup-node@v6
               with:
               node-version-file: .nvmrc
      -          cache: npm
      -          cache-dependency-path: package-lock.json
      +          cache: pnpm
      +          cache-dependency-path: pnpm-lock.yaml
               registry-url: 'https://registry.npmjs.org'
      
    2. npmpnpmに、npxpnpxに置き換え
  3. 不要になったpackage-lock.jsonの削除

あとがき

結果としては打ち辛いこと以外満足している。

正直pnpmも登場した当初はYarn同様に、いけ好かないツールだなと思っていたが使ってみるとインストール速度が明らかに早く、npmの比較にならないこと(比べてないけど、たぶんYarnより早いと思う)や、なんかpnpmの勢いが強いので、流石にもうnpmは使えないなと判断して移行することにした。

pnpmが流行っている背景としては、恐らくYarn v3が酷評されているのと、連日のnpmパッケージの脆弱性騒動が背景にあるのだと思う。実際打ち辛いこと以外使いやすいし、勢いが出るのも納得という感じ。

ただpnpmが打ちづらすぎるのは何とかなってほしい。typoを狙ったpnmpみたいな悪意のあるパッケージが絶対にありそう。

てかv10のドキュメントではエイリアスの設定を推奨しているのに、v11からは削除されてて部分的にpnの記述が残ってるのはどうなのか…。ドキュメントの整備が追い付いていないのだろうか?

英語版でも同じなので何故削除したのかよくわからない。まぁエイリアス前提だとCIとかだるいし、そこが前提でないほうがドキュメント的にはよいと思うが…。

2026/01/28(水)GitHub Actionsからnpm publish出来なくなってたのを対応した

投稿日:

一年ぶりくらいにGitHub Actionsを使ってnpmパッケージを更新しようとしたら何かこけたので、通るようにした時にやったこと。

事象

なんかこんな感じのエラーが出てnpm publishに失敗した。

npm notice 1.6kB package.json
npm notice Tarball Details
npm notice name: @lycolia/ts-boilerplate-generator-cli
npm notice version: 0.28.1
npm notice filename: lycolia-ts-boilerplate-generator-cli-0.28.1.tgz
npm notice package size: 14.8 kB
npm notice unpacked size: 79.1 kB
npm notice shasum: 2ba5920ab2b46695bd996e86bf67b6a7cdb980cd
npm notice integrity: sha512-YHU4X10pXE7HP[...]RKmFhCpP4Gnmw==
npm notice total files: 25
npm notice
npm notice Publishing to https://registry.npmjs.org/ with tag latest and default access
npm notice Access token expired or revoked. Please try logging in again.
npm error code E404
npm error 404 Not Found - PUT https://registry.npmjs.org/@lycolia%2fts-boilerplate-generator-cli - Not found
npm error 404
npm error 404
npm error 404
npm error 404 Note that you can also install from a
npm error 404 tarball, folder, http url, or git url.

npm error A complete log of this run can be found in: /home/runner/.npm/_logs/2026-01-27T00_45_59_837Z-debug-0.log
Error: Process completed with exit code 1.

'@lycolia/ts-boilerplate-generator-cli@0.28.1' is not in this registry.

起きていたこと

  1. npmjsにあるAccess Tokensが全部消えてた
  2. Trusted publishing for npm packagesという話で、OIDC[1]を使ってGitHubと連携しないとGitHubなどのCI/CD、つまり自動化処理・バッチ処理からnpm publishできなくなっていた
  3. これに対応するためにはnpm CLI version 11.5.1か、それ以降が必要
  4. またnpmjsのOIDC連携をするためには2FA認証が必須で、そのためにはパスキーが必要
  5. Access Tokenは最大90日までになり、無制限のものはなくなった
    • Access Tokenでnpm publishを行う場合、2FAしていないとできない

対応に必要なこと

  1. npmjsに2FA登録する。要パスキー
  2. npmjsからGitHubリポジトリへのOIDC連携
  3. GitHubリポジトリにあるnpm publishしているyamlの修正
  4. npmのバージョンアップ

やったこと

  1. npmjsにパスキーを登録
  2. npmjsからGitHubリポジトリへのOIDC連携
    1. パッケージのSettingsタブを開き、Trusted publisherにリポジトリ情報を登録する
      Enviroment nameは第三者向けの項目[2]なので、設定しなくていい
    2. Set up connectionボタンを押して連携する
  3. GitHub Actionsのワークフローを直す
    1. permissionsの部分を足し、npm publishenvは不要なので削除
       name: npm publish on push to main
       on:
       push:
           branches:
           - main
      +permissions:
      +  id-token: write
      +  contents: read
       jobs:
       publish-to-npm:
           runs-on: ubuntu-latest
           steps:
           - uses: actions/checkout@v4
           - uses: actions/setup-node@v4
               with:
               node-version-file: '.nvmrc'
               cache: npm
               cache-dependency-path: package-lock.json
               registry-url: 'https://registry.npmjs.org'
           - name: npm continuous install
               run: npm ci
           - name: npm build
               run: npm run build
           - name: run publish
               run: npm publish
      -        env:
      -          NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH }}
      
  4. .nvmrcのNode.jsのバージョンをv24.13.0にした
    • このバージョンにすると自動的にnpmのバージョンが適合したため
  5. この後、GitHub Actionsを使ってnpm publishに成功すると、パッケージページやバージョン履歴ページには次のような表示が出るようになる

パスキー使いたくない問題

パスキーは端末依存で環境間共有の面倒さやGoogle縛りになるのが嫌などで入れたくない人も少なくないだろう。私もそう思う。正直パスキーありきのサービスは困る。

取り敢えず私の場合はEdgeを使っていて、Android Edgeへのパスキー共有はできないものの、いったんpublishするだけなら問題ないので、Edgeのパスキーを使うことにした。

どうしてもパスキーを使いたい、ほかの環境でも同期したいが、Googleに頼りたくない場合はKeePassXCというOSSを使うのが一つの手だ。

KeePassXCは暗号化されたデータベースファイルにIDとパスワードや、パスキーを記録するソフトウェアだ。複数環境への同期はNASなりSSHなり、クラウドストレージなどに鍵DBを保存して、それぞれの環境から読み書きすることで実現できる。

KeePassXCにはEdgeの拡張もあり、PCの中でKeePassXCを起動していればEdgeの拡張と同期してIDパスワードやパスキーを上手く管理してくれるようだった。ただ拡張機能が起動する前にKeePassXCが起動していないと手動で接続しないといけないなど、地味に面倒だった。

ただ調べた限りKeePassXCには公式のAndroidアプリがなく、サードパーティーアプリは毎回鍵ファイルを読みに行く実装のようで、オフライン時にも使うことのあるスマホでは運用に厳しさを感じた。逆に完全オフライン版もあるが、これはこれでAndroid側でDBを更新した時に別環境に飛ばすのが手間になるだろうからイマイチだ。

もう一つの選択肢としてはBitwardenを使う方法もある。こちらは公式がAndroidアプリを出しているほか、同期用のストレージを自前で用意する手間もかからない。

Bitwardenは、いわば1Passwordの無料版みたいな感じと言えるだろう。なお、BitwardenにはOSS版もあるので、セルフホスト運用もできるようだが、詳しくは調べていない。

私はBitwardenを軽く試してみたが、Edgeの自動入力機能に干渉しており、EdgeのパスワードDBを消し去らないとEdgeとBitwarden両方のパスワード入力補助が出てきて非常に邪魔だったことや、アニメーション設定をOFFにしても入力フィールドが飛び跳ねるアニメーションが出てきて嫌だったので、結局諦めた。せめて独立して動いてほしかった。

トラブルシューティング

Edgeで2FA認証しようとしたらパスキーがこけた

画像のような状態になった場合、何度かやり直すといけた。

「Two-factor authentication or granular access token with bypass 2fa enabled is required to publish packages.」と言われる

パスキーを使った2FAを登録することで解決した。

「npm error code EOTP」と言われる

npm notice Publishing to https://registry.npmjs.org/ with tag latest and default access
npm error code EOTP
npm error This operation requires a one-time password from your authenticator.
npm error You can provide a one-time password by passing --otp=<code> to the command you ran.
npm error If you already provided a one-time password then it is likely that you either typoed
npm error it, or it timed out. Please try again.

このようなエラーが出る場合、GitHub ActionsのWorkflowsのyamlファイルのルートに以下の記述が足りないので足す。

permissions:
  id-token: write  # Required for OIDC
  contents: read

「npm error code ENEEDAUTH」と言われる

npm error code ENEEDAUTH
npm error need auth This command requires you to be logged in to https://registry.npmjs.org/
npm error need auth You need to authorize this machine using `npm adduser`

このようなエラーが出る場合、npmのバージョンが古いので11.5.1以上にすることで解決する。

あとがき

正直npmjsを利用するのはもうやめようかと思う。ぶっちゃけもうNode.jsと積極的に関わりたくないし、代替技術を探したいと感じた。少なくともプライベートではそう思う。

TypeScriptに限界を感じてきたでも書いたが、Node.jsのエコシステム周りには甚だうんざりしてきており、今回の件でより、さらに、もっと嫌になった。

取り敢えず静的解析とかそういうのは欲しいし、テストもしたい、ほんでLinuxフレンドリーで、Windowsでも動いてくれるとなおよい。簡単なツールを書くことが多いのもありコンパイル言語よりはインタプリタ言語のほうが好ましい。

そう考えるとやはり浮かんでくるのはPHPになってくるあたり、21年前に触れた私の初めてのプログラミング言語との出会いに戻ってくるあたりが面白い。PHPerはPHPerから逃れられない宿命でもあるのかもしれない。

今は肩書上フロントエンドエンジニアとかいうのを仕事にしているが、そこまで性に合っていない気もしてきているし、Web系のバックエンドではPHPの仕事もまだまだあるので、これを機にPHPに戻るのも一つありだとは思った。

関係ない話、何ならadiaryのせいでTypeScriptよりPerlの方が好感を持ててきているまであるので、私はたぶんどうかしているのだと思う。


  1. OpenID Connectの略。いわゆるOAuthを使って別サービスのアカウントで連携処理を行うもの。
  2. OIDC連携はnpmjsのアカウントとリポジトリを紐づけるためのもので、publisher以外の人間が作業する場合に必要になるものと思われるが詳しくは調べていない。