vue3 框架
和 vite 工具
來講,其中的實現與架構設計無不是一個 複雜而龐大的工程
,而支撐這些工程能順利執行的無不是一個又一個的輪子,正好最近有在閱讀 vue3 和 vite3
的原始碼,發現一些較實用的輪子,在這裡分享給大家。如果你想對 前端工程化
有所涉獵的話,我相信下面的工具總有一款是你想要的!
picocolors 是一個可以在終端修改輸出字元樣式的 npm
包,說直白點就是給字元新增顏色;
可能有的同學想到了,這不是跟 chalk 一樣的嗎?
沒錯,他們的作用其實就是一樣的!
為什麼選擇 picocolors:
所以大家明白選什麼了吧!
當然因為 picocolors
包比較小,所以功能邊界沒有 chalk
的全面,但是用在一些自研等絕大部分的需求中是完全可以滿足的。
注意:
因為歷史等原因
vue3
目前還在使用chalk
;vite 已全面用
picocolors
替代作為終端樣式輸出;不過
chalk
為了優化,在最近的最新版本 v5 中已剔除依賴包;
prompts
vs enquirer
vs inquirer
乍一看,可能有的同學會有點懵,其實一句話交代就是:其實他們三都是用來 實現命令列互動式介面
的工具;
之所以放在一起是因為 vue3
和 vite
所使用的互動式工具不盡相同;
工具名 | 何處使用 | 大小 | 周下載量 | github 地址 |
---|---|---|---|---|
prompts | vite | 187 kB | 18,185,030 | prompts |
enquirer | vue3 | 197 kB | 13,292,137 | enquirer |
inquirer | 其它 | 87.7 kB | 24,793,335 | inquirer |
npm 近兩年下載熱度趨勢:
簡單總結:
其實 vite
起初也是使用的 enquirer
,只是後面為了滿足使用者跨平臺使用時出現的 bug,才替換成了 prompts
,當然也並不是說 enquirer
不好,只是場景不同,所以選擇會有所不同罷了;
其實如果你想在自己的專案中使用 互動式介面
工具,我這邊還是比較推薦 inquirer
的,畢竟社群受歡迎程度和功能都是完全滿足你的需求的。
cac 是一個用於構建 CLI 應用程式的 JavaScript 庫;
通俗點講,就是給你的 cli 工具增加自定義一些命令,例如 vite create
,後面的 create
命令就是通過 cac 來增加的;
因為該庫較適用於一些自定義的工具庫中,所以只在 vite
中使用, vue3
並不需要該工具;
主要是因為 vite 的工具是針對一些自定義的命令等場景不是特別複雜的情況;
我們看看 cac 的優勢
:
commander
和 yargs
;cli.option
、cli.version
、cli.help
cli.parse
即可搞定大部分需求;當然,如果你想寫一個功能較多的 cli 工具,也是可以選擇
commander
和yargs
的;不過一些中小型的 cli 工具我還是比較推薦
cac
的;
npm-run-all 是一個 cli
工具,可以並行、或者按順序執行多個 npm
指令碼;npm-run-all
在 vite
工具原始碼中有使用;
通俗點講就是為了解決官方的 npm run 命令
無法同時執行多個指令碼的問題,它可以把諸如 npm run clean && npm run build:css && npm run build:js && npm run build:html
的一長串的命令通過 glob 語法簡化成 npm-run-all clean build:*
一行命令。
提供三個命令:
npm-run-all
:-s
和 -p
引數的簡寫,分別對應序列和並行;# 依次執行這三個任務命令 npm-run-all clean lint build # 同時執行這兩個任務命令 npm-run-all --parallel lint build # 先序列執行 a 和 b, 再並行執行 c 和 d npm-run-all -s a b -p c d
run-s
:為 npm-run-all --serial
的縮寫;run-p
:為 npm-run-all --parallel
的縮寫;上面只是簡單的介紹了下,想要了解更多實用功能的,可以去官網檢視;
最後:這個庫屬實是好用,良心推薦!
semver 是一個語意化版本號管理的 npm
庫;semver
在 vue3
框架原始碼和 vite
工具原始碼中都有使用;
說直白一點,你在開發一個開源庫的時候,肯定會遇到要提醒使用者不同版本號不同的情況,那麼如何去判斷使用者版本過低,semver
就可以很好的幫助你解決這個問題;
semver
內建了許多方法,比如 判斷一個版本是否合法,判斷版本號命名是否正確,兩個版本誰大誰小之類
等等方法;
如下列一些官網的例子:
const semver = require('semver') semver.valid('1.2.3') // '1.2.3' semver.valid('a.b.c') // null semver.clean(' =v1.2.3 ') // '1.2.3' semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // true semver.gt('1.2.3', '9.8.7') // false semver.lt('1.2.3', '9.8.7') // true semver.minVersion('>=1.0.0') // '1.0.0' semver.valid(semver.coerce('v2')) // '2.0.0' semver.valid(semver.coerce('42.6.7.9.3-alpha')) // '42.6.7'
更多使用方法 詳見檔案
minimist 是一個命令列引數解析工具;minimist
在 vue3
框架原始碼和 vite
工具原始碼中都有使用;
使用:
const args = require('minimist')(process.argv.slice(2))
例如:
# 執行以下命令 vite create app -x 3 -y 4 -n5 -abc --beep=boop foo bar baz # 將獲得 { _: [ 'foo', 'bar', 'baz' ], x: 3, y: 4, n: 5, a: true, b: true, c: true, beep: 'boop' }
特別要說明的是返回值其中首個 key 是_
,它的值是個陣列,包含的是所有沒有關聯選項的引數。
如果你的工具在終端有較多的引數,那麼這個工具就非常的適合您!
magic-string 是一個用於操作字串和生成源對映的小而快的庫;
其實它最主要的功能就是對一些原始碼和龐大的 AST
字串做輕量級字串的替換;
在 vite
工具原始碼和 @vue/compiler-sfc
中大量使用;
使用:
import MagicString from 'magic-string'; const s = new MagicString('problems = 99'); // 替換 problems -> answer s.overwrite(0, 8, 'answer') s.toString() // 'answer = 99' // 生成 sourcemap var map = s.generateMap({ source: 'source.js', file: 'converted.js.map', includeContent: true })
fs-extra 是一個強大的檔案操作庫
, 是 Nodejs fs 模組
的增強版;
這個就不多講了,因為它在千錘百煉之下只能形容它是 YYDS
,檢視 更多官方檔案。
chokidar 是一款專門用於檔案監控的庫;chokidar
只在 vite
工具原始碼中有使用;
其實 Node.js 標準庫中提供 fs.watch
和 fs.watchFile
兩個方法用於處理檔案監控,但是為什麼我們還需要chokidar
呢?
主要是由於 相容性不好、無法監聽、監聽多次
等大量影響效能的問題;
chokidar 用法:
const chokidar = require('chokidar'); const watcher = chokidar.watch('file, dir, glob, or array', { ignored: /(^|[\/\\])\../, persistent: true }); watcher .on('add', path => console.log(`File ${path} has been added`)) .on('change', path => console.log(`File ${path} has been changed`)) .on('unlink', path => console.log(`File ${path} has been removed`)) .on('addDir', path => console.log(`Directory ${path} has been added`)) .on('unlinkDir', path => console.log(`Directory ${path} has been removed`)) .on('error', error => console.log(`Watcher error: ${error}`)) .on('ready', () => console.log('Initial scan complete. Ready for changes')) .on('all', (event, path) => console.log(event,path)) .on('raw', (event, path, details) => { log('Raw event info:', event, path, details); });
fast-glob 是一個快速批次匯入、讀取檔案的庫; fast-glob
只在 vite
工具原始碼中有使用;
基本語法:
*
:匹配除斜杆、影藏檔案外的所有檔案內容;
**
:匹配零個或多個層級的目錄;
?
:匹配除斜杆以外的任何單個字元;
[seq]
:匹配 []
中的任意字元 seq;
如何使用:
const fg = require('fast-glob'); const entries = await fg(['.editorconfig', '**/index.js'], { dot: true });
在 vite
中使用:
vite
工具中 import.meta.glob
方法(如下)就是基於這個庫來實現,所以如果你在自己的工具庫中有批次檔案等的操作,這個庫是以很不錯的選擇;
const modules = import.meta.glob('./dir/*.js', { query: { foo: 'bar', bar: true } })
vite
通過 fast-glob
工具把它生成如下程式碼
// vite 生成的程式碼 const modules = { './dir/foo.js': () => import('./dir/foo.js?foo=bar&bar=true').then((m) => m.setup), './dir/bar.js': () => import('./dir/bar.js?foo=bar&bar=true').then((m) => m.setup) }
debug 是一個模仿 Node.js
核心偵錯技術的小型 JavaScript
偵錯程式,在適用於 Node.js
和 Web 瀏覽器
都可使用;debug
只在 vite
工具原始碼中有使用;
說直白點就是你可以使用 debug 來對你的程式進行 毫秒級別時間差的統計
對你程式程式碼進行優化;
使用:
var debug = require('debug')('http') , http = require('http') , name = 'My App'; // fake app debug('booting %o', name); http.createServer(function(req, res){ debug(req.method + ' ' + req.url); res.end('hello\n'); }).listen(3000, function(){ debug('listening'); }); // fake worker of some kind require('./worker');
如果你對你的程式碼或者自研的工具等有較高效能要求,強烈建議可以使用
debug
來進行調式。
dotenv 是一個零依賴模組,可將 .env 檔案
中的環境變數載入到 process.env
中;dotenv
只在 vite
工具原始碼中有使用;
如何使用:
建立 .env 檔案
S3_BUCKET="YOURS3BUCKET" SECRET_KEY="YOURSECRETKEYGOESHERE"
使用
import * as dotenv from 'dotenv' dotenv.config() console.log(process.env)
esbuild 是一個基於 Go 語言開發的 JavaScript 打包工具,被 Vite 用於開發環境的依賴解析;
相比傳統的打包工具,主打效能優勢,在構建速度上可以快 10~100 倍;
到現在知道為啥
vite
為啥快了吧,esbuild
就是第一功臣。
優勢:
使用:
esbuild
在 API 層面上非常簡潔, 主要的 API 只有兩個: Transform
和 Build
, 這兩個 API 可以通過 CLI, JavaScript, Go 的方式呼叫;
transform:呼叫這個API能將 ts
,jsx
等檔案轉換為js檔案;
// cli exbuild ./test.ts --loader=ts // 輸出 const str = 'Hello World'; // js api呼叫 const esbuild = require('esbuild'); const fs = require('fs'); const path = require('path'); const filePath = path.resolve(__dirname, 'test.ts'); const code = esbuild.transformSync(fs.readFilesync(filePath), { loader: 'ts', }) console.log(code); // 輸出 // { // code: 'const str = 'Hello World'', // map: '', // warnings: [] // }
build:整合了transform
後的程式碼,可以將一個或者多個檔案轉換並儲存為檔案;
// cli esbuild test.ts --outfile=./dist/test.js // { errors: [], warnings: [] } // js api呼叫 const esbuild = require('esbuild'); const path = require('path'); const result = esbuild.buildSync({ entryPoints: [path.resolve(__dirname, 'test.ts')], outdir: path.resolve(__dirname, 'dist'), }); console.log(result); // { errors: [], warnings: [] }
更多詳細使用可檢視連結
rollup 是一個 JavaScript 模組打包器
,可以將小塊程式碼編譯成大塊複雜的程式碼,我們熟悉的 vue、react、vuex、vue-router 等都是用 rollup 進行打包的。
在 vite
中的生產環境(Production) 就是基於 rollup
打包來構建主要程式碼的。
使用:
1、建立 rollup.config.js
檔案
2、組態檔
export default { input: 'src/index.js', output: { name: 'amapUpper', file: 'dist/amapUpper.js', format: 'umd' }, plugins: [] };
3、執行
{ "scripts": { "dev": "rollup -i src/index.js -o dist/bundle.js -f es" }, }
4、執行 npm run dev
ws 是一個簡單易用、速度極快且經過全面測試的 WebSocket 使用者端
和 伺服器
實現;完全可以是 Socket.io
的替代方案;ws
只在 vite
工具原始碼中有使用。
說直白一點就是通過 ws
,咱們可以實現伺服器端和使用者端的長連線,且通過 ws
物件,就可以獲取到 使用者端傳送過來的資訊
和 主動推播資訊給使用者端
。
使用:
1、server.js
const WebSocket = require('ws') const WebSocketServer = WebSocket.Server; // 建立 websocket 伺服器 監聽在 3000 埠 const wss = new WebSocketServer({port: 3000}) // 伺服器被使用者端連線 wss.on('connection', (ws) => { // 通過 ws 物件,就可以獲取到使用者端傳送過來的資訊和主動推播資訊給使用者端 var i=0 var int = setInterval(function f() { ws.send(i++) // 每隔 1 秒給連線方報一次數 }, 1000) })
2、client.js
const WebSocket = require('ws') const ws = new WebSocket('ws://localhost:3000') // 接受 ws.on('message', (message) => { console.log(message) // 當數位達到 10 時,斷開連線 if (message == 10) { ws.send('close'); ws.close() } })
connect 是一個最早期的 HTTP 伺服器框架,亦可稱為中介軟體外掛;express
就是基於此框架做的擴充套件;
注意:從 vite2
開始官方已從依賴 koa
轉成 connect
了;
至於為什麼使用 connect
而不是 koa
,咱們看官方的回答:
大概意思就是:由於大部分邏輯應該通過外掛勾點而不是中介軟體來完成,因此對中介軟體的需求大大減少;所以使用 connect
優先順序會高於 Koa
。
esno 是一個基於 esbuild
的 TS/ESNext
的 Node.js
執行時;
說直白點就是可以類似 ts-node
一樣直接執行 TS 檔案
,那為甚麼還用 esno
呢?
因為 esno
是基於 esbuild
執行的,esbuild
有多快,上面我們有講到了吧,這裡就不復述了。
使用:
{ "scripts": { "start": "esno index.ts" }, "dependencies": { "esno": "*" } }
npm run start
tsup 是一個輕小且無需設定的,由 esbuild
支援的打包工具;
它可以直接把 .ts、.tsx
轉成不同格式 esm、cjs、iife
的檔案,快速打包你的工具庫;
使用:
1、安裝 tsup
pnpm i tsup -D
2、在根目錄下的 package.json
中設定
{ "scripts": { "dev": "pnpm run build -- --watch --ignore-watch examples", "build": "tsup src/index.ts --dts --format cjs,esm" }, }
vitepress 是在 vuepress
的基礎上實現的靜態網站生成器,區別在於 vitepress
是建立在 vite
之上做的開發;
優勢:
vite
而不是 webpack
,所有更快的啟動時間,熱過載等;vue3
來減少 js 的有效負載;所以如果你想寫一個線上檔案倉庫,那麼
vitepress
就是一個很好的選擇。
vitest 是一個由 vite
提供支援的快速單元測試框架。
優勢:
由 Vite ⚡️ 提供支援的極速單元測試框架。
與 Vite 的設定通用,watch 模式下極快的反應(相當於測試中 HMR)。
可以對 Vue/React 元件進行測試。
開箱即用 Typescript/JSX/ESM(這一點我想配過 jest 的人應該懂是什麼意思)
與 Jest 幾乎相同的 API,同時也有 Jest 的快照功能(這個非常好用!)
模擬 DOM
生成測試覆蓋率
ESM優先,頂級等待
開箱即用的 TypeScript / JSX 支援
套件和測試的過濾、超時、並行
等等
所以你還有什麼理由不使用
vitest
呢?
其實細心的同學可能會發現,目前 vue3
和 vite3
都是一個 monorepo
倉庫,且都是使用 pnpm workspace
來進行倉庫管理的;
所以瞭解 monorepo
和 pnpm workspace
對原始碼的閱讀也是有很大的幫助的;
關於這塊更多詳細可以檢視《如何入門 vite 原始碼》進行了解。
https://juejin.cn/post/7094984070999834655
當然,上面的分享的工具庫只是在原始碼中使用 場景較多的庫
,還有一些庫由於 場景較少
所以這裡沒有做詳細的解釋說明,如果您想了解原始碼中的哪個工具庫,歡迎補充,取捨後我會做及時的更新;