前七天一路追 npm run dev,終於追到最後一棒:Vite 被啟動了。
終端機接著出現:
Local: http://localhost:5173/
以前我看到這裡的反應大概是:
好,React 跑起來了。
但這句話其實把很多東西混在一起。
localhost:5173到底是誰開的?React 嗎?
Vite
→ 啟動開發用的 Web Server
→ 讓瀏覽器可以透過 localhost 開啟這個專案
React
→ 建立、更新畫面上的 UI
所以執行:
npm run dev
一路找到 Vite 之後,Vite 會在我的電腦上啟動一個開發用的 Web Server。
我一開始聽到 Web Server,腦中會直接想到正式網站上的 Nginx。
其實概念沒有差那麼遠。
可以先把它想成一個櫃台:
瀏覽器
↓
來要網站內容
↓
Web Server
↓
把網站檔案送回去
只是現在這個櫃台不是架在遠端主機,而是直接開在我自己的電腦上。
某種程度上,可以把它理解成「把前端暫時放在自己的電腦上給瀏覽器看」。
不過正式一點的說法,是:
在本機啟動開發伺服器,而不是正式部署。
localhost:5173 到底是什麼?再拆一次:
localhost
= 我自己的這台電腦
5173
= Vite dev server 正在使用的 port
localhost 通常會對應到本機的 loopback 位址,例如 127.0.0.1 或 ::1。
所以當我在 Chrome 輸入:
http://localhost:5173
意思很接近:
我要用 HTTP,去找我自己這台電腦上 5173 這個 port 的程式。
而此時正在那裡等的,就是 Vite dev server。
可以把電腦想成一棟大樓:
localhost
= 這棟大樓
5173
= 5173 號房間
Vite dev server
= 正在 5173 號房間裡等的人
所以 Vite 並不是「創造 localhost」。
localhost 本來就代表自己這台電腦;Vite 做的是在某個 port 上開始等待瀏覽器連線。
我們只看瀏覽器和 Vite 之間發生什麼:
Chrome
↓
http://localhost:5173
↓
找到自己這台電腦
↓
找到 5173 port
↓
找到 Vite dev server
↓
送出 HTTP Request
瀏覽器第一次打開首頁時,概念上會送出類似:
GET / HTTP/1.1
Host: localhost:5173
意思差不多就是:
我要這個網站的
/首頁。
Vite 收到之後,就回一個 HTTP Response。
內容裡通常會先有:
index.html
所以這一段其實是:
Chrome
↓
HTTP GET /
↓
Vite dev server
↓
HTTP Response
↓
index.html
這時我才突然把 localhost 和 Web Server 接起來。
原來瀏覽器不是「直接看到我的 React 專案」。
它還是在做網站平常就在做的事情:
送 Request,等 Server 回 Response。
只是 Server 現在剛好就在自己的電腦裡。
在一般 Vite React 專案裡,index.html 可能會看到:
<script type="module" src="/src/main.jsx"></script>
瀏覽器讀到這行,就知道還要繼續取得:
/src/main.jsx
main.jsx 又可能再引入:
import App from './App.jsx'
所以流程其實比較像:
瀏覽器
↓
Vite dev server
↓
index.html
↓
main.jsx
↓
App.jsx
↓
React 建立 UI
瀏覽器不是一開始就知道 App.jsx 在哪裡。
它是從 HTML 一路追進去的。
React 專案裡很常看到:
function App() {
return <h1>Hello</h1>
}
這個:
<h1>Hello</h1>
是 JSX。
它不是瀏覽器原生可以直接當成一般 JavaScript 執行的語法。
所以在開發流程裡,Vite 也會協助處理這些開發中的程式碼,讓瀏覽器最後拿到可以執行的內容。
目前我只先記:
Vite
├─ 啟動開發用 Web Server
├─ 在本機 port 等瀏覽器連線
├─ 透過 HTTP 提供 index.html、JS、CSS 等內容
├─ 協助處理 JSX 等開發中的程式碼
└─ 讓開發時的更新更即時
我的答案現在會是:
心智模型上可以這樣想,但它比較準確叫「本機開發伺服器」。
因為 Vite dev server 是為了讓我開發方便,不是拿來當正式網站伺服器。
那如果真的準備上線,又會發生什麼?
npm run build 又是在做什麼?我原本會以為,既然:
npm run dev
可以把網站跑起來,那正式上線是不是也讓它一直跑就好了?
不是。
在一般 Vite 專案裡,package.json 通常會有類似:
{
"scripts": {
"dev": "vite",
"build": "vite build"
}
}
所以當我執行:
npm run build
流程其實又跟前面很像:
npm run build
↓
npm 讀 package.json
↓
找到 scripts 裡的 build
↓
執行 vite build
↓
Vite 開始建置專案
這裡的 build,可以先理解成:
把開發中的前端專案,整理成適合正式部署的成品。
開發時,我看到的是:
src/
├─ main.jsx
├─ App.jsx
├─ CSS
└─ 其他原始碼
執行 build 之後,Vite 預設會產生:
dist/
├─ index.html
└─ assets/
├─ index-xxxx.js
└─ index-xxxx.css
所以我現在會把 dist 想成:
網站的成品資料夾。
最重要的是:
npm run build
≠ 把網站上傳到網路
它只是先把「可以拿去部署的成品」做出來。
真正部署還是下一步:把這些成品交給正式環境的 Web Server 或部署平台。
所以我可以這樣分:
npm run dev
= 我要繼續寫程式
= 開啟本機開發伺服器
npm run build
= 我準備交貨了
= 產生正式部署用的成品
開發時:
我的瀏覽器
↓
localhost:5173
↓
Vite dev server
↓
開發中的專案
正式上線後則可能是:
使用者瀏覽器
↓
正式網址
↓
Nginx 等 Web Server
↓
dist/
這時正式網站通常不需要一直跑 Vite dev server。
Vite 前面已經完成它其中一個工作:把專案 build 成可以部署的成品。
所以現在我比較能分清楚:
Vite
= 開發/建置工具
React
= 建立與更新 UI
Nginx
= 正式環境提供網站內容的 Web Server
到這裡,終於可以把前八天接成一條線:
npm install
↓
建立 node_modules
↓
npm run dev
↓
npm 讀 package.json 的 scripts
↓
找到 node_modules/.bin/vite
↓
啟動 Vite
↓
Vite 啟動 dev server
↓
localhost:5173 等瀏覽器連線
↓
瀏覽器用 HTTP 請求 /
↓
取得 index.html
↓
載入 main.jsx / App.jsx
↓
React 建立 UI
↓
開發完成
↓
npm run build
↓
Vite 建置專案
↓
產生 dist/
↓
準備正式部署
localhost:5173不是 React 自己開的。Vite 會在我的電腦上啟動一個開發用 Web Server,瀏覽器透過 HTTP 連到它、取得網站內容;開發完成後,再透過npm run build把專案整理成適合部署的成品。React 的主要工作,則是建立與更新 UI。