正所謂:工欲善其事,必先利其器!寫一個開源的專案也不例外,就拿在國內很火的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 並不需要該工具;
cac 的優勢:
和
yargs;
cli.version
、cli.help
cli.parse
即可搞定大部分需求;
commandernpm-run-all和
cacyargs
的;不過一些中小型的cli 工具我還是比較推薦
的;
4. npm-run-all
是一個 cli 工具,可以並行、或依序執行多個 npm
腳本;npm-run-all
在vite
工具原始碼中有使用;通俗點講就是為了解決官方的
無法同時執行多個腳本的問題,它可以把諸如npm run clean && npm run build:css && npm run build:js && npm run build:html
的一長串的指令透過glob 語法簡化成npm-run-all clean build:*
一行指令。
可以帶-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
npm-run-all --serial
的縮寫;
npm-run-all --parallel
的縮寫;
官網這個庫屬實是好用,良心推薦!5. semver
是語意化版本號管理的npm 函式庫;semver
在vue3
框架原始碼和vite
工具原始碼中都有使用;說直白一點,你在開發一個開源程式庫的時候,一定會遇到要提醒使用者不同版本號不同的情況,那麼如何去判斷使用者版本過低,
就可以很好的幫助你解決這個問題;
內建了許多方法,例如判斷一個版本是否合法,判斷版本號命名是否正確,兩個版本誰大誰小之類
等等;
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 是一个命令行参数解析工具; 使用: 例如: 特别要说明的是返回值其中首个 key 是 如果你的工具在终端有较多的参数,那么这个工具就非常的适合您! magic-string 是一个用于操作字符串和生成源映射的小而快的库; 其实它最主要的功能就是对一些源代码和庞大的 在 使用: fs-extra 是一个强大的 这个就不多讲了,因为它在千锤百炼之下只能形容它是 chokidar 是一款专门用于文件监控的库; 其实 Node.js 标准库中提供 主要是由于 chokidar 用法: fast-glob 是一个快速批量导入、读取文件的库; 基本语法: 如何使用: 在 debug 是一个模仿 说直白点就是你可以使用 debug 来对你的程序进行 使用: 如果你对你的代码或者自研的工具等有较高性能要求,强烈建议可以使用 dotenv 是一个零依赖模块,可将 如何使用: 1、创建 2、使用 esbuild 是一个基于 Go 语言开发的 JavaScript 打包工具,被 Vite 用于开发环境的依赖解析; 相比传统的打包工具,主打性能优势,在构建速度上可以快 10~100 倍; 到现在知道为啥 优势: 使用: 1、transform:调用这个API能将 2、build:整合了 更多详细使用可查看链接 rollup 是一个 在 使用: 1、创建 2、配置文件 3、运行 4、执行 ws 是一个简单易用、速度极快且经过全面测试的 说直白一点就是通过 使用: 1、server.js 2、client.js connect 是一个最早期的 HTTP 服务器框架,亦可称为中间件插件; 注意:从 至于为什么使用 大概意思就是:由于大部分逻辑应该通过插件钩子而不是中间件来完成,因此对中间件的需求大大减少;所以使用 esno 是一个基于 说直白点就是可以类似 因为 使用: tsup 是一个轻小且无需配置的,由 它可以直接把 使用: 1、安装 2、在根目录下的 vitepress 是在 优势: 所以如果你想寫一個線上文件倉庫,那麼 vitest 是一個由 優勢: 由 Vite ⚡️ 提供支援的極速單元測試框架。 與 Vite 的配置通用,watch 模式下極快的反應(相當於測試中 HMR)。 可以對 Vue/React 元件進行測試。 開箱即用Typescript/JSX/ESM(這一點我想配過jest 的人應該懂是什麼意思) 與Jest 幾乎相同的API,同時也有Jest 的快照功能(這個非常好用!) #模擬DOM vitest vue3 monorepo 場景較多的庫6. 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' }
_
,它的值是个数组,包含的是所有没有关联选项的参数。7. 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
})
8. fs-extra
文件操作库
, 是 Nodejs fs 模块
的增强版;YYDS
,查看 更多官方文档。9. chokidar
chokidar
只在 vite
工具源码中有使用;fs.watch
和 fs.watchFile
两个方法用于处理文件监控,但是为什么我们还需要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);
});
10. 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)
}
11. debug
Node.js
核心调试技术的小型 JavaScript
调试程序,在适用于 Node.js
和 Web 浏览器
都可使用;debug
只在 vite
工具源码中有使用;毫秒级别时间差的统计
对你程序代码进行优化;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
来进行调式。12. dotenv
.env 文件
中的环境变量加载到 process.env
中;dotenv
只在 vite
工具源码中有使用;.env 文件
S3_BUCKET="YOURS3BUCKET"
SECRET_KEY="YOURSECRETKEYGOESHERE"
import * as dotenv from 'dotenv'
dotenv.config()
console.log(process.env)
13. esbuild
vite
为啥快了吧,esbuild
就是第一功臣。
esbuild
在 API 层面上非常简洁, 主要的 API 只有两个: Transform
和 Build
, 这两个 API 可以通过 CLI, JavaScript, Go 的方式调用;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: []
// }
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: [] }
14. rollup
JavaScript 模块打包器
,可以将小块代码编译成大块复杂的代码,我们熟悉的 vue、react、vuex、vue-router 等都是用 rollup 进行打包的。vite
中的生产环境(Production) 就是基于 rollup
打包来构建主要代码的。rollup.config.js
文件export default {
input: 'src/index.js',
output: {
name: 'amapUpper',
file: 'dist/amapUpper.js',
format: 'umd'
},
plugins: []
};
{
"scripts": {
"dev": "rollup -i src/index.js -o dist/bundle.js -f es"
},
}
npm run dev
15. ws
WebSocket 客户端
和 服务器
实现;完全可以是 Socket.io
的替代方案;ws
只在 vite
工具源码中有使用。ws
,咱们可以实现服务端和客户端的长连接,且通过 ws
对象,就可以获取到 客户端发送过来的信息
和 主动推送信息给客户端
。 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)
})
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()
}
})
16. connect
express
就是基于此框架做的扩展;vite2
开始官方已从依赖 koa
转成 connect
了;connect
而不是 koa
,咱们看官方的回答:connect
优先级会高于 Koa
。17. esno
esbuild
的 TS/ESNext
的 Node.js
运行时;ts-node
一样直接运行 TS 文件
,那为甚么还用 esno
呢?esno
是基于 esbuild
运行的,esbuild
有多快,上面我们有讲到了吧,这里就不复述了。{
"scripts": {
"start": "esno index.ts"
},
"dependencies": {
"esno": "*"
}
}
npm run start
18. tsup
esbuild
支持的打包工具;.ts、.tsx
转成不同格式 esm、cjs、iife
的文件,快速打包你的工具库;tsup
pnpm i tsup -D
package.json
中配置{
"scripts": {
"dev": "pnpm run build -- --watch --ignore-watch examples",
"build": "tsup src/index.ts --dts --format cjs,esm"
},
}
19. vitepress
vuepress
的基础上实现的静态网站生成器,区别在于 vitepress
是建立在 vite
之上做的开发;
vite
而不是webpack
,所有更快的啟動時間,熱重載等;vue3
來減少js 的有效負載;vitepress
就是一個很好的選擇。 20. vitest
vite
提供支援的快速單元測試框架。
所以你還有什麼理由不使用
其它其實細心的同學可能會發現,目前 呢?
和
vite3 都是一個
monorepo倉庫,而且都是使用
pnpm workspace 來進行倉庫管理的;
和
pnpm workspace 對原始碼的閱讀也是有很大的幫助的;
關於這塊更多詳細可以查看《如何入門vite 源碼》進行了解。 https://juejin.cn/post/7094984070999834655
當然,上面的分享的工具庫只是在原始碼中使用 ,還有一些庫由於
場景較少 所以這裡沒有做詳細的解釋說明,如果您想了解源碼中的哪個工具庫,歡迎補充,取捨後我會做及時的更新;
原文網址:https://juejin.cn/post/7124112069355372581作者:易師傅