iT邦幫忙

2026 iThome 鐵人賽

DAY 4
0
JavaScript

JavaScript為什麼筆記本系列 第 4

Day 04|npm run dev 小整理

  • 分享至 

  • xImage
  •  

Day 1 到 Day 3 寫完後,我原本有一種「好,這段差不多懂了」的感覺。
不過我覺得要回想一下。

從頭問自己:

npm run dev
↓
接下來到底發生什麼?

一路答到:

npm 讀 package.json
↓
找到 scripts.dev
↓
得到 "vite"

然後就卡住了。

更尷尬的是,看到 PATHshellnode_modules/.bin,每個字都好像看過,但要我自己串成一句話,就開始亂掉 @@


vite 之後發生什麼?

npm run dev

前半段我已經可以自己說:

npm run dev
↓
npm 讀 package.json
↓
找到 scripts.dev
↓
得到 "vite"

問題是:

vite

只是一個 command 名稱,又不是完整路徑。

那到底是誰負責去找它?

這時我才發現,前幾天雖然一直看到 shell 這個字,但......其實沒有真的把它放進腦袋裡。

先把 Terminal、Shell、PATH 分開

我目前先用最白話的方式理解:

Terminal
= 我輸入指令、看輸出的地方

Shell
= 負責接收、理解並處理我輸入的 command 的程式

PATH
= shell 尋找外部 command 時會依序查看的「資料夾清單」

甚至有點把 shell 和 bash 搞反。

比較正確的關係是:

shell
├── bash
├── zsh
└── fish

bashzsh 都是 shell 的不同種類。

所以可以先把 shell 想成一個「負責聽指令的人」。

例如我在 Terminal 輸入:

vite

概念上就是:

我在 Terminal 輸入 vite
↓
shell 收到「vite」
↓
shell:這個 command 在哪?
↓
去看 PATH

PATH 不是一條路徑,而是一份有順序的資料夾清單R!

這裡是我最容易講錯的地方。

我以前聽到 PATH,腦中很容易把它想成:

某一條檔案路徑

但在現在這個問題裡,更有用的理解是:

PATHshell 用來搜尋 command 的一串資料夾清單,而且有順序。

概念上例如:

node_modules/.bin
/usr/local/bin
/usr/bin
/bin

如果 shell 要找:

vite

它就會依序嘗試:

node_modules/.bin/vite
/usr/local/bin/vite
/usr/bin/vite
/bin/vite

找到前面的,就可以先用前面的。

所以 PATH 裡放的不是:

node_modules/.bin/vite

而是整個資料夾:

node_modules/.bin

這個差一小段,心智模型卻差很多。

為什麼 npm 要把整個 .bin 資料夾放進 PATH?

我一開始還問了一個有點笨但其實很關鍵的問題:

為什麼 npm 不直接把 node_modules/.bin/vite 放進 PATH 就好?

答案是:因為 PATH 的工作本來就是放「資料夾」,不是列出每一個 command

假設 .bin 裡有:

node_modules/.bin/
├── vite
├── eslint
└── tsc

npm 只要把:

node_modules/.bin

放進 PATH,shell 之後就可以依照不同名稱去找:

vite   → node_modules/.bin/vite
eslint → node_modules/.bin/eslint
tsc    → node_modules/.bin/tsc

這樣就不用為每一個 command 各塞一條完整路徑。

npm 真正幫忙的是這一段

所以 npm run dev 中間這段:

scripts.dev = "vite"
↓
npm 執行 script 時準備 PATH
↓
把相關的 node_modules/.bin 排到前面
↓
shell 收到「vite」
↓
shell 按 PATH 的順序找
↓
找到 node_modules/.bin/vite

這裡我之前很容易講成:

npm 把 node_modules/.bin/vite 放進 PATH

這是不精確的。

比較精準的是:

npm 把 node_modules/.bin 這個**資料夾加進 PATH 的前段;shell 再去這個資料夾裡找 vite **。

為什麼要讓專案自己的 .bin 排前面?

這裡又多懂一點。

假設我的電腦全域剛好也有一個 Vite,而專案自己也有:

全域 Vite:7
專案 Vite:8

如果執行:

npm run dev

npm script 的環境會讓專案相關的 node_modules/.bin 排在 PATH 很前面,所以 shell 通常會先找到:

專案/node_modules/.bin/vite

也就是專案自己的 Vite。

這其實很合理。

不同專案可能需要不同版本:

專案 A → Vite 6
專案 B → Vite 8

如果全部都只靠電腦全域那一份,就很容易出現:

我這台可以跑
同事那台版本不同
CI 又是另一個版本

所以我現在會記成一句:

PATH 有順序,而 npm 會讓專案自己的 command 優先被找到。

node_modules/.bin/vite 之後呢?

這就接回 Day 3。

我們看過:

ls -l node_modules/.bin/vite

在 macOS/Linux 上,常會看到類似:

node_modules/.bin/vite -> ../vite/bin/vite.js

所以:

node_modules/.bin/vite
↓
只是 command 入口
↓
指向 node_modules/vite/bin/vite.js

而 Vite 套件自己的 package.json 裡,也會有類似:

"bin": {
  "vite": "bin/vite.js"
}

也就是它自己宣告:

command 名稱:vite
↓
入口檔:bin/vite.js

到這裡,Day 1~Day 3 才真的接成一條線。

把整條流程重新畫一次

現在從頭走:

npm run dev
↓
npm 讀專案的 package.json
↓
找到 scripts.dev
↓
得到 "vite"
↓
npm 準備執行 script 的環境
↓
相關的 node_modules/.bin 排進 PATH 前面
↓
shell 收到 command:vite
↓
shell 按 PATH 的順序找
↓
找到 node_modules/.bin/vite
↓
.bin/vite 指向 Vite 套件的入口
↓
node_modules/vite/bin/vite.js
↓
Vite 開始執行

以前我的版本大概只有:

npm run dev
↓
網站跑起來

現在中間終於不是一團黑箱。

跟著做:不要看答案,再驗證一次

這次先不要看上面的流程圖。

1. 看 npm script 裡的 PATH

npm run env | grep '^PATH='

先只找一件事:

node_modules/.bin

是不是出現在很前面。

2. 直接問 npm script 裡的 vite 在哪

如果 package.json 還有這個暫時的 script:

"where-vite": "command -v vite"

執行:

npm run where-vite

看看是不是找到:

.../node_modules/.bin/vite

3. 再看 .bin/vite 指去哪

ls -l node_modules/.bin/vite

把:

.bin/vite

和:

vite/bin/vite.js

重新接起來。

4. 最後補空格~~~

npm run dev
↓
npm 讀 __________
↓
找到 __________
↓
得到 "vite"
↓
npm 執行 script 時準備 __________
↓
把 __________ 排到前面
↓
__________ 按順序找 vite
↓
找到 node_modules/.bin/vite
↓
指向 node_modules/vite/bin/vite.js

這次真正發現自己卡在哪:不是 package.json,也不是 .bin,而是中間的 shell → PATH 還沒接起來。

這次最容易搞錯的三件事

1. PATH 不是一條路徑

在這個情境裡,PATH 比較像是有順序的資料夾清單

2. npm 不是把 .bin/vite 放進 PATH

npm 放進 PATH 的是像:

node_modules/.bin

shell 再去裡面找 vite

3. shell 不是 bash 的其中一種

方向反了xddd

比較像:

shell
├── bash
└── zsh

bashzsh 是 shell 的不同實作。

一邊照顧快三個月的娃娃一邊自問自答,晚安


上一篇
Day 03|node_modules/.bin 是什麼?
下一篇
Day 05|package.json 到底是什麼?為什麼 npm 要讀它?
系列文
JavaScript為什麼筆記本8
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言