1578 字
8 分鐘

pnpm init --init-package-manager 怎麼固定版本?11.25.0 會改看 latest

執行 pnpm init --init-package-manager 後,如果新建立的專案 pin 不是你目前正在執行的 pnpm 版本,不一定是指令失敗。pnpm 11.25.0 的行為已改成查 registry 的 latest tag,讓新專案可以直接固定到較新的可用版本;但這也會讓本機、CI 和文章裡的預期看起來不一致。

先講結論:從 pnpm 11.25.012.0.0 開始,--init-package-manager 會嘗試把 pin 設成 registry 的 latest;如果查詢失敗、太慢、被 offline/minimumReleaseAge/trustPolicy 阻擋,就回退到目前執行中的 pnpm,而且不會因為 latest 比目前版本舊就降版。 這個行為和「如何更新 pnpm 本身」是兩件事。

先確認你看到的是執行版本還是專案 pin#

不要只貼一個 pnpm --version 就判斷專案版本。先把三種資訊分開留下:

Terminal window
pnpm --version
node --version
pnpm config get registry

接著檢查專案 manifest 與 lockfile 裡是否已有 package manager 宣告:

Terminal window
node -e 'const p=require("./package.json"); console.log(JSON.stringify({packageManager:p.packageManager, devEngines:p.devEngines}, null, 2))'
rg -n 'packageManager|packageManagerDependencies' package.json pnpm-lock.yaml

這裡有三個可能不同的值:正在執行的 pnpm、package.json 裡的 devEngines.packageManager 或 legacy packageManager,以及 lockfile 裡解析後的 packageManagerDependencies。它們不一致時,先記錄來源,不要直接刪除其中一個。

--init-package-manager 在 11.25.0 之後怎麼決定版本#

官方 pnpm 文件對這個旗標的規則,可以整理成以下順序:

條件pnpm init --init-package-manager 的結果
可以查到 registry 的 latest以 latest 作為候選 pin;它可以比目前執行版本新
latest 比目前執行版本舊不把既有選擇降到較舊版本
registry 查詢失敗、逾時或使用 offline回退到目前正在執行的 pnpm
minimumReleaseAge 或 trustPolicy 讓候選版本不可用回退到目前正在執行的 pnpm
使用 --no-init-package-manager不新增 package manager pin

這個設計兼顧了兩個目標:新專案可以跟上 registry 的最新 stable 版本,而離線或受限環境不會因為「無法查 latest」就讓 pnpm init 失敗或無限等待。也因此,同一條指令在有網路的開發機與隔離 CI runner 可能留下不同 pin,必須把結果納入 code review。

實際跑一次,差異要看兩個檔案#

在空白資料夾或 disposable branch 測試,不要直接在正式 workspace 裡覆蓋既有 manifest:

Terminal window
mkdir pnpm-init-pin-check
cd pnpm-init-pin-check
pnpm init --init-package-manager
git diff -- package.json pnpm-lock.yaml

如果資料夾還沒有 git repository,git diff 不一定會顯示未追蹤的 package.json;可以直接檢查內容與 lockfile:

Terminal window
node -e 'const p=require("./package.json"); console.log(JSON.stringify({packageManager:p.packageManager, devEngines:p.devEngines}, null, 2))'
rg -n 'packageManager|packageManagerDependencies' package.json pnpm-lock.yaml

從 pnpm v11 開始,專案 pin 主要會寫到 devEngines.packageManager;較新的文件也說明,解析後的實際版本會記在 pnpm-lock.yamlpackageManagerDependencies。部分專案仍會看到 legacy packageManager 的 exact version,因此升級或重建時要以目前專案格式和 lockfile 一起審查。

為什麼本機和 CI 會得到不同結果#

最常見不是 pnpm 隨機選版本,而是兩邊的輸入不同:

  • 本機能連 registry,CI 使用 --offline 或沒有 DNS。
  • 本機沒有 minimum release age,CI 的設定拒絕剛發布的 latest。
  • 本機的 pnpm 已較新,CI 仍使用舊版執行器。
  • 兩邊的 registry、trust policy 或認證設定不同。
  • 指令在 workspace 子套件執行,但真正的 pin 只應寫在 workspace root。

官方文件特別提醒,在 workspace 內的子套件執行 pnpm init --init-package-manager 時,這個旗標只對 root 有效。若你希望整個 monorepo 使用同一個 pnpm,應在 root 產生或審查 pin,再讓 CI 顯式執行該版本,不要期待每個 subpackage 都有自己的 package manager 設定。

不想自動寫 pin,就用 no-init#

如果專案版本由 Corepack、mise、Volta、asdf 或 CI image 統一管理,初始化時可以明確關閉 pin:

Terminal window
pnpm init --no-init-package-manager

這不代表專案沒有版本管理,而是把責任留給既有工具。相反地,如果團隊希望新專案自帶可審查的 pnpm 版本,就保留 --init-package-manager,然後把 package.jsonpnpm-lock.yaml 一起提交,並在 CI 印出:

Terminal window
pnpm --version
pnpm install --frozen-lockfile

這樣 code review 看到 pin 變更時,可以分辨它是初始化時查到新的 latest,還是依賴更新造成的 lockfile 變更。

不要把 init 的 pin 和 pnpm 自身更新混在一起#

--init-package-manager 是「在專案寫入或更新 package manager pin」;它不等同於把目前使用中的 pnpm 全域升級。pnpm 11.25.0 的 release note 也提醒,pnpm update -g 不再負責改變 pnpm 本身的版本;需要更新 pnpm 執行器時,應依官方建議使用 pnpm self-update 或團隊既有的版本管理流程。

排查時可以依序問:

  1. 是哪個 pnpm 執行了 init
  2. registry 的 latest 當時解析成什麼?
  3. package.json 寫的是 devEngines.packageManager 還是 legacy packageManager
  4. lockfile 是否留下 packageManagerDependencies
  5. CI 是否有 offline、minimumReleaseAge 或 trust policy?

回答完這五題,通常就能判斷版本差異是預期的解析結果,還是真正的環境漂移。

結論:把 latest 查詢結果當成輸入的一部分#

pnpm 11.25.0 之後,pnpm init --init-package-manager 不再只看「目前正在執行的版本」,而會嘗試查 registry 的 latest;pnpm 12.0.0 也沿用這個方向。可用網路時 pin 可能前進到較新版本,查詢受限時則回退到 running version,而且不會把選擇降到較舊版本。

因此,遇到「init 後版本不一樣」時,先檢查 devEngines.packageManager、legacy packageManager、lockfile、registry 與 workspace root。需要穩定重現時,把實際 pin、Node、pnpm 和 CI 網路政策一起提交與驗證;不需要 pin 時,初始化就明確使用 --no-init-package-manager

常見問題#

Q: pnpm init --init-package-manager 為什麼會寫入比目前 pnpm 更新的版本?#

A: pnpm 11.25.0 起會查 registry 的 latest,官方允許候選 pin 比目前執行版本新。這是初始化時的版本解析,不代表本機的 pnpm --version 已經同步變更。

Q: offline 時執行 init 會失敗嗎?#

A: 官方文件描述的 fallback 是使用目前正在執行的 pnpm;registry 無法連線、查詢太慢、--offline 或政策拒絕候選版本時,不應為了查 latest 而卡住。仍要把產生的 manifest 與 lockfile 納入審查。

Q: workspace 子套件可以各自固定不同 pnpm 嗎?#

A: --init-package-manager 在 workspace 子套件執行時只對 root 有效。若真的需要不同版本,應先確認工具與 CI 是否支援該拓樸;一般 monorepo 建議在 root 保留單一可審查 pin。

參考資料:

pnpm v11.25.0 release notes

pnpm Docs:pnpm init

pnpm Docs:package.json 的 package manager 設定

pnpm init --init-package-manager 怎麼固定版本?11.25.0 會改看 latest
https://laplusda.com/posts/pnpm-init-package-manager-latest-pin/
作者
Zero
發佈於
2026-09-01
許可協議
CC BY-NC-SA 4.0
這篇文章有幫助嗎?

回報錯字、失效連結,或告訴我你想看的延伸主題。