許多現在的前端開發框架都有如 Webpack 或 Parcel 之類的 bundle 工具,而 Vue 卻選擇了另外開發自己的構建工具 - Vite,不只設定簡單,效能還驚人的好,甚至在 Vue 以外的框架也能使用。 官方網站已經介紹了不少它的功能及運作方式,但身為工程師應該要有的好奇心,我想不只靠文件,還希望藉由閱讀 Vite 原始程式碼,介紹 Vite 的內部的設計方式,以及它為什麼可以這麼快。
五倍學院被 Vue 框架耽誤的建置工具
View Slide
五倍學院Vite /vit/
五倍學院關公面前耍小刀
五倍學院今天內容:新手以上,資深未滿
五倍學院npm run dev 之後發生什麼事?
五倍學院自我介紹
五倍學院愛玩、愛現,喜歡冷門的玩具網站開發者、講師、作家技術推廣、企業訓練、技術諮詢部落格:kaochenlong.com高見龍@eddiekao
五倍學院第26刷 發售中 發售中發售中
五倍學院已絕版
五倍學院歡迎加好友
五倍學院我是個 Rails Developer
五倍學院Rails 4: assets pipelineRails 5 ~ 6: webpackRails 7: importmap
五倍學院vite_rails
五倍學院不只可以用在 Vue 專案上!
五倍學院一般的香草 JS 專案可以用
五倍學院連 React 也能用 Vite!身在曹營心在漢真香
五倍學院模組化
五倍學院no module石器時代
五倍學院CommonJS、AMD、ESM大亂鬥!戰國時代
五倍學院ESM 原生支援美好時代
五倍學院打包工具 vs 建置工具Bundler vs Building Tool
五倍學院打包工具將多個原始檔(例如 .js、.css 或圖片)合併成較少數量的文件。通常可透過壓縮程式碼、圖片或是檔案名雜湊等方式,提高性能和快取利用率。例:Webpack, Parcel, Rollup
五倍學院建置工具在不同階段或環境執行的各種任務,例如跑測試、原始碼轉譯、CSS 樣式預處理、圖片最佳化等。或是讓開發者可以在開時階段使用較新的語法,但最後再將其轉換成瀏覽器看的懂的內容。例:Gulp, npm script
五倍學院那 Vite 算是哪一種?
五倍學院Vite 本身就是個 dev server
五倍學院閱讀原始碼
五倍學院Why?
五倍學院你不需要每行都看懂
五倍學院使用工具:Visual Studio Codesual Studio Code
五倍學院Goto / Ctrl + -
五倍學院{"name": "vite","version": "4.4.9","type": "module","license": "MIT","author": "Evan You","description": "Native-ESM powered web dev build tool",// ..略.."dependencies": {"esbuild": "^0.18.10","postcss": "^8.4.27","rollup": "^3.27.1"}}vite/package.jsonv4.4.9
五倍學院$ npm run dev
五倍學院CLICommand-Line Interface
五倍學院const cli = cac('vite')node/cli.ts
五倍學院
五倍學院const { createServer } = await import('./server')node/cli.ts
五倍學院const watcher = chokidar.watch([root, ...config.configFileDependencies, config.envDir],resolvedWatchOptions,) as FSWatchernode/server/index.ts
五倍學院watcher.on('change', async (file) => {file = normalizePath(file)moduleGraph.onFileChange(file)await onHMRUpdate(file, false)})node/server/index.ts
五倍學院try {fetchedModule = await import(/* @vite-ignore */base +acceptedPathWithoutQuery.slice(1) +`?${explicitImportRequired ? 'import&' : ''}t=${timestamp}${query ? `&${query}` : ''}`)} catch (e) {warnFailedFetch(e, acceptedPath)}node/client/client.ts
五倍學院Vite 是一個 dev server
五倍學院原始碼檔案異動時...
五倍學院透過 client(ws) 發動 import
五倍學院Pre-Bundling
五倍學院現在不是原生支援 ESM 了嗎?
五倍學院大量的 import request?
五倍學院esbuild
五倍學院掃描原始碼裡的 import
五倍學院node_modules/.vite
五倍學院httpServer.listen = (async (port: number, ...args: any[]) => {try {// ensure ws server startedws.listen()await initServer()} catch (e) {httpServer.emit('error', e)return}return listen(port, ...args)}) as anynode/server/index.ts
五倍學院if (cachedMetadata && cachedMetadata.hash === getDepHash(config, ssr)) {log?.('Hash is consistent. Skipping. Use --force to override.')return cachedMetadata}node/optimizer/optimizer.ts
五倍學院啟動 → 檢查 Hash
五倍學院Module Graph
五倍學院Module Node
五倍學院async ensureEntryFromUrl(rawUrl: string,ssr?: boolean,setIsSelfAccepting = true,): Promise {return this._ensureEntryFromUrl(rawUrl, ssr, setIsSelfAccepting)}node/server/moduleGraph.ts
五倍學院// for incoming urls, it is important to:// 1. remove the HMR timestamp query (?t=xxxx) and the ?import query// 2. resolve its extension so that urls with or without extension all map to// the same moduleasync resolveUrl(url: string, ssr?: boolean): Promise {url = removeImportQuery(removeTimestampQuery(url))const mod = await this._getUnresolvedUrlToModule(url, ssr)if (mod?.id) {return [mod.url, mod.id, mod.meta]}return this._resolveUrl(url, ssr)}node/server/moduleGraph.ts
五倍學院// main transform middlewaremiddlewares.use(transformMiddleware(server))node/server/index.ts
五倍學院小結
五倍學院Vite 出生在對的時代
五倍學院瀏覽器對 ESM 的原生支援
五倍學院importmap 也是
五倍學院把粗重活交給別人處理
五倍學院原始碼 → Webpack → 打包 →丟給 dev server
五倍學院原始碼 → Vite → 給瀏覽器 →有異動再 import
五倍學院esbuild + rollup
五倍學院解決了 DX 不佳的問題DX = Developer Experience
五倍學院真香!
五倍學院工商服務
五倍學院talentd.cc