npx

你可能不懂 npx

好吧,也有可能只有我不懂 🤣 最近在深入研究一些前端的技術,才發現一直以來對 npx 的理解好像有一些誤解,於是花了點時間釐清一下錯誤的觀念。

1. How npx works

先提一下 npx 的使用辦法,通常只要下以下指令:

$ npx [npm_package_name]

就可以執行 [npm_package_name] 的指令,ex:

$ npx eslint --version
v9.21.0

npx 執行的邏輯如下:

1.1 先找 local 的 dependency

會先看當前目錄有沒有安裝該 dependency,以上述的 eslint 來說,就會先看目前目錄是否有安裝 eslint,有的話就會先用目前目錄的 eslint 來執行之後的指令。

1.2 再找 ~/.npm/_npx

npm cache 相關的資料都會存在 ~/.npm 裡面,因此只要之前有用 npx 執行過 package 的指令,也都會被 cache 到 ~/.npm/_npx 裡面,舉例來說,我在 2022 的時候用 npx 執行過 create-react-app

$ npx create-react-app my-app-name

如果去 ~/.npm/_npx 看會發現:

npx

確實找得到 cache,而當時的版本是 5.0.1,因此之後只要你執行 npx create-react-app,在 local 沒有安裝 package 的前提下,都會直接拿這個 cache 來執行 create-react-app 的指令:

$ npx create-react-app --version
5.0.1

你可能會問,既然是 cache 那是不是等他過期,npx 就會去拉最新版了?答案是:npm 的 cache 是沒有期限的

npm will not remove data by itself: the cache will grow as new packages are installed.

因此除非你主動刪除 cache($ npm cache clean --force npm 不建議),否則 cache 永遠都會在,也因此如果沒有特別加上 package 的版本,那很有可能永遠都會用第一次 npx 安裝的 package 版本來執行指令。

1.3 安裝最新版本

如果 local dependencies 和 ~/.npm/_npx 裡面都沒有這個套件的話,npx 才會去安裝目前這個 package 的最新版本:

$ npx eslint --version
# 會先詢問是否確認要安裝,輸入 y 才會繼續安裝並執行指令
Need to install the following packages:
  [email protected]
Ok to proceed? (y)

如果希望用最新版的 package 來執行,則在 package 後面加上 @latest 即可:

$ npx create-react-app@latest --version
5.1.0

2. npx 和 npm exec 的差別

npm exec 和 npx 做的事情類似,差別在於如何處理 arguments,以下列指令為例

$ npx foo@latest bar --package=@npmcli/foo 

npm 會先解析要去哪裡找 foo@latest(local, _npx, 還是安裝新的),再用解析完的 package 路徑去執行指令:

$ foo bar --package=@npmcli/foo

而這段指令如果用 npm exec 會等同於:

$ npm exec -- foo@latest bar  --package=@npmcli/foo

如果是用 npm exec 執行以下指令:

$ npm exec foo@latest bar --package=@npmcli/foo

則 npm 會先解析 --package=@npmcli/foo,然後才去執行

$ foo@latest bar

3. Reference

npm-cache
npx
npm-exec

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top