大家好,我是 Maneshwar。我正在開發 git-lrc,一個微型 AI 程式碼審查器,它會在每次提交時執行。它是免費的,原始碼已發佈在 GitHub 上。請為 git-lrc 點贊,幫助開發者發現這個專案。歡迎試用並分享您的回饋,以幫助我們改進專案。

你一生中大約執行過 1000 次npm run dev

你看到終端閃爍了一下。

您已切換到瀏覽器。

奇蹟發生了。

但你真的了解事情的真相嗎?我是說,真的了解嗎?

今天我們將深入理解 shell、進程生成、模組圖、熱模組替換、React 快速刷新。

步驟 0:按下 Enter 鍵

npm run dev

你的 shell 會在PATH中尋找npm ,通常它位於nvm安裝 Node 的目錄中,或是位於類似/usr/local/bin/npm系統路徑下。然後它會將控制權交給 npm CLI,而 npm CLI 本身只是一個 Node.js 腳本。

然後 npm 會做一件事:讀取你的package.json

{
  "scripts": {
    "dev": "vite"
  }
}

它找到了"dev": "vite"並準備執行它。

步驟 1:npm 產生一個子進程

npm 會暫時將./node_modules/.bin加入你的PATH中,然後產生一個子程序來執行dev指令。

因此, "vite"解析為./node_modules/.bin/vite ,它是指向node_modules/vite/bin/vite.js中實際Vite二進位檔案的符號連結。

沒什麼神奇的,只是Node執行了一個JS檔而已。

步驟 2:Vite 啟動

Vite會讀取你的vite.config.js (或.ts )文件,註冊插件,並在提供任何內容之前執行一些非常巧妙的操作。

esbuild 預先包裝技巧

Vite 使用 Go 編寫的esbuild ,速度快得驚人,可以預處理你的node_modules依賴項。

它有兩個作用:

  1. 將 CommonJS 轉換為 ESM。瀏覽器無法原生載入require() ,esbuild 會重寫它。

  2. esbuild 將包含大量內部文件的套件合併成一個。例如, lodash有 600 多個小檔案。 esbuild 會將它們合併,因此瀏覽器只需發出一個請求,而不是 600 個。

結果快取在.vite/deps/中。執行 touch node_modules指令?快取將被清除。

否則,重新啟動時將完全跳過此步驟。

圖片描述

步驟 3:開發伺服器其實就是一個 HTTP 伺服器。

Vite 在localhost:5173上啟動一個普通的 Node.js HTTP 伺服器。

沒有webpack開發伺服器的魔法,也沒有複雜的中間件鏈。

當瀏覽器請求文件時,Vite:

  1. 從磁碟讀取

  2. 即時轉換(JSX → JS,TypeScript → JS, .css → 注入的<style>

  3. 將其用作原生ES 模組

瀏覽器本身使用<script type="module">來處理模組解析。

關鍵在於: Vite 在開發模式下根本不會打包你的原始碼。

瀏覽器將每個檔案作為 ES 模組單獨取得。

這就是為什麼無論專案大小,Vite 的開發啟動速度幾乎是瞬間完成的,因為它只處理瀏覽器實際請求的內容。

圖片描述

每個箭頭都代表一個真實的HTTP請求。瀏覽器會自動為你完成圖遍歷。

步驟 4:模組圖

當請求檔案時,Vite 會建立一個內部模組依賴關係圖,也就是誰匯入了什麼的映射。

圖片描述

這個圖是惰性的,只有被要求的節點才會存在其中。

如果你從未導航到某個路由,那麼這些元件就永遠不會被獲取,也不會出現在圖中。

這就是HMR速度快的原因。

當檔案發生變更時,Vite 不會掃描所有程式碼。

它只是沿著這條曲線走。

第五步:保存文件-精彩之處就在這裡。

5a. 作業系統立即通知 Vite

Vite 使用chokidar ,它封裝了作業系統原生的檔案系統事件:

作業系統 | 應用程式介面 | 機制 |

|---|---|---|

| Linux | inotify | 核心直接監視 inode |

| macOS | FSEvents | 核心服務檔案系統事件 API |

| Windows | ReadDirectoryChangesW | Win32 API |

零輪詢。作業系統會在編輯器刷新到磁碟的瞬間立即通知 Vite。

5b. 遍歷圖,找到 HMR 邊界

Vite 從更改的檔案開始向上遍歷模組圖,查找第一個透過import.meta.hot.accept()註冊了 HMR 處理程序的祖先。

圖片描述

使用 React,你永遠不需要自己寫import.meta.hot.accept()

@vitejs/plugin-react插件(使用React Fast Refresh )會在元件轉換時自動將此程式碼注入到每個元件檔案中。您對此不可見。

如果找不到邊界,則一直到main.jsx都會重新載入整個頁面。

當您編輯vite.config.js或不支援 HMR 的非元件 JS 實用程式時,就會發生這種情況。

5c. 伺服器僅重新轉換已更改的文件

Vite 會透過其插件管道 JSX 轉換、任何 Babel 插件等重新執行Button.jsx

結果是在記憶體中建立了一個新的 ES 模組。

5d. 瀏覽器透過動態導入取得新模組

HMR客戶端(Vite注入到頁面中的一個小型腳本)被告知有更新可用,並呼叫:

import('/components/Button.jsx?t=1718023456789')

?t=timestamp查詢參數用於清除快取。瀏覽器看到一個之前從未取得過的 URL,會發出真正的 HTTP 請求,從而取得新的模組。

5e. 模組交換hot.disposehot.accept

Vite 的 HMR 執行時圍繞兩個函數建置,這兩個函數需要您(或者,如果是 React,則需要插件)在import.meta.hot中註冊:

// In a module that wants to handle its own updates:

// Clean up before this module is replaced —
// cancel timers, unsubscribe, remove listeners.
import.meta.hot.dispose((data) => {
  clearInterval(timer)
})

// Receive the freshly imported module and re-wire things.
import.meta.hot.accept((newModule) => {
  // newModule is the updated exports
})

一個微妙但重要的細節:Vite 的 HMR 並不會真的取代鏈上所有導入的原始模組物件。

接收模組(即 HMR 邊界)負責接收新的匯出資料並套用它們。

這種簡化的模型使得 Vite 可以省去重寫每個導入器的昂貴工作,並且足以滿足幾乎所有實際開發場景的需求。

dispose用於取消setInterval 、取消訂閱 store 或移除事件監聽器,任何如果舊模組被棄用就會造成記憶體洩漏的操作。

關於 CSS 的說明:樣式表的處理方式略有不同。當.css檔案發生變更時,Vite 不會動態地重新匯入 JS 模組,而是將<link> (或<style> )標籤替換為更新後的樣式表,這樣可以避免未樣式化內容的閃爍。

步驟 6:React 快速刷新執行實際的重新渲染。

React Fast Refresh 是 React 團隊建構的一個獨立系統。當新的元件模組發佈時,它會:

  1. 比較鉤子函數的簽名。如果ButtonuseState, useEffect之前和之後都具有useState, useEffect則狀態會被保留。加入或移除鉤子函數?狀態只會重置該元件。

  2. 尋找 React fiber 樹中所有存活的實例

  3. 精確地重新渲染僅針對受影響的子樹。父元件不會重新渲染。兄弟元件也不會重新渲染。只有更改後的元件及其子元件會重新渲染。

圖片描述

這就是為什麼在表單填寫過程中,您可以編輯元件的樣式,而表單不會重設的原因。表單狀態保存在父元件或同級元件中——快速刷新從未觸及過它。

完整畫面

圖片描述

這為什麼重要?

如果你使用的是 webpack 的開發伺服器,即使啟用了熱模組替換 (HMR),檔案儲存也會觸發打包重建。對於中等規模的專案來說,這會導致儲存和瀏覽器更新之間出現明顯的延遲。

使用 Vite 的原生 ESM 方法,伺服器幾乎什麼都不做(只需轉換一個檔案),瀏覽器只需取得一個 URL,快速刷新功能只需修改一個子樹。

整個往返過程通常非常快,隨著專案的增長,速度也會保持很快。

這並非微小的改進。

它從根本上改變了你的工作方式——編輯→查看結果幾乎是瞬間完成的。

圖片描述

人工智慧代理編寫程式碼速度很快。但它們也會悄無聲息地刪除邏輯、改變行為,甚至引入漏洞——而且不會事先通知你。你往往會在生產環境中才發現這些問題。

git-lrc 解決了這個問題。它會接入 git commit 流程,並在每次提交之前檢查差異。只需 60 秒即可完成設定。完全免費。 *

歡迎任何反饋或貢獻!它已上線,原始碼公開,任何人都可以使用。

⭐ 在 GitHub 上給它點個星:

{% github=https://github.com/HexmosTech/git-lrc


原文出處:https://dev.to/lovestaco/what-happens-when-you-run-npm-run-dev-ae9


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝17   💬11   ❤️1
590
🥈
alicec
📝1   ❤️2
81
🥉
我愛JS
💬2  
7
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
📢 贊助商廣告 · 我要刊登