前言 大家好,我是小满,正所谓:工欲善其事,必先利其器! 写一个开源的项目也不例外,就拿在国内很火的vue3框架和vite工具来讲,其中的实现与架构设计无不是一个复杂而庞大的工程,而支撑这些工程能顺利运行的无不是一个又一个的轮子,正好最近有在阅读vue3和vite3的源码,发现一些较实用的轮子,在这里分享给大家。 如果你想对前端工程化有所涉猎的话,我相信下面的工具总有一款是你想要的!1。picocolors picocolors是一个可以在终端修改输出字符样式的npm包,说直白点就是给字符添加颜色; 可能有的同学想到了,这不是跟chalk一样的吗? 没错,他们的作用其实就是一样的! 为什么选择picocolors:无依赖包;比chalk体积小14倍,速度快2倍;支持CJS和ESM项目; 所以大家明白选什么了吧! 当然因为picocolors包比较小,所以功能边界没有chalk的全面,但是用在一些自研等绝大部分的需求中是完全可以满足的。注意: 因为历史等原因vue3目前还在使用chalk;vite已全面用picocolors替代作为终端样式输出;不过chalk为了优化,在最近的最新版本v5中已剔除依赖包;2。promptsvsenquirervsinquirer 乍一看,可能有的同学会有点懵,其实一句话交代就是:其实他们三都是用来实现命令行交互式界面的工具; 之所以放在一起是因为vue3和vite所使用的交互式工具不尽相同; 工具名 何处使用 大小 周下载量 github地址 prompts vite 187kB 18,185,030 prompts enquirer vue3 197kB 13,292,137 enquirer inquirer 其它 87。7kB 24,793,335 inquirer npm近两年下载热度趋势: 简单总结:其实vite起初也是使用的enquirer,只是后面为了满足用户跨平台使用时出现的bug,才替换成了prompts,当然也并不是说enquirer不好,只是场景不同,所以选择会有所不同罢了;其实如果你想在自己的项目中使用交互式界面工具,我这边还是比较推荐inquirer的,毕竟社区受欢迎程度和功能都是完全满足你的需求的。3。cac cac是一个用于构建CLI应用程序的JavaScript库; 通俗点讲,就是给你的cli工具增加自定义一些命令,例如vitecreate,后面的create命令就是通过cac来增加的; 因为该库较适用于一些自定义的工具库中,所以只在vite中使用,vue3并不需要该工具; 为什么不用commanderoryargs? 主要是因为vite的工具是针对一些自定义的命令等场景不是特别复杂的情况; 我们看看cac的优势:超轻量级:没有依赖,体积数倍小于commander和yargs;易于学习:只需要学习4APIcli。option、cli。version、cli。helpcli。parse即可搞定大部分需求;功能强大:启用默认命令,可以像使用git的命令一样方便去使用它,且有参数和选项的校验、自动生成help等完善功能;当然,如果你想写一个功能较多的cli工具,也是可以选择commander和yargs的; 不过一些中小型的cli工具我还是比较推荐cac的;4。npmrunall npmrunall是一个cli工具,可以并行、或者按顺序执行多个npm脚本;npmrunall在vite工具源码中有使用; 通俗点讲就是为了解决官方的npmrun命令无法同时运行多个脚本的问题,它可以把诸如npmruncleannpmrunbuild:cssnpmrunbuild:jsnpmrunbuild:html的一长串的命令通过glob语法简化成npmrunallcleanbuild:一行命令。 提供三个命令:npmrunall:可以带s和p参数的简写,分别对应串行和并行;依次执行这三个任务命令npmrunallcleanlintbuild同时执行这两个任务命令npmrunallparallellintbuild先串行执行a和b,再并行执行c和dnpmrunallsabpcd复制代码runs:为npmrunallserial的缩写;runp:为npmrunallparallel的缩写;上面只是简单的介绍了下,想要了解更多实用功能的,可以去官网查看; 最后:这个库属实是好用,良心推荐!5。semver semver是一个语义化版本号管理的npm库;semver在vue3框架源码和vite工具源码中都有使用; 说直白一点,你在开发一个开源库的时候,肯定会遇到要提醒用户不同版本号不同的情况,那么如何去判断用户版本过低,semver就可以很好的帮助你解决这个问题; semver内置了许多方法,比如判断一个版本是否合法,判断版本号命名是否正确,两个版本谁大谁小之类等等方法; 如下列一些官网的例子:constsemverrequire(semver)semver。valid(1。2。3)1。2。3semver。valid(a。b。c)nullsemver。clean(v1。2。3)1。2。3semver。satisfies(1。2。3,1。x2。5。05。0。07。2。3)truesemver。gt(1。2。3,9。8。7)falsesemver。lt(1。2。3,9。8。7)truesemver。minVersion(1。0。0)1。0。0semver。valid(semver。coerce(v2))2。0。0semver。valid(semver。coerce(42。6。7。9。3alpha))42。6。7复制代码6。minimist minimist是一个命令行参数解析工具;minimist在vue3框架源码和vite工具源码中都有使用; 使用:constargsrequire(minimist)(process。argv。slice(2))复制代码 例如:执行以下命令vitecreateappx3y4n5abcbeepboopfoobarbaz将获得{:〔foo,bar,baz〕,x:3,y:4,n:5,a:true,b:true,c:true,beep:boop}复制代码 特别要说明的是返回值其中首个key是,它的值是个数组,包含的是所有没有关联选项的参数。 如果你的工具在终端有较多的参数,那么这个工具就非常的适合您!7。magicstring magicstring是一个用于操作字符串和生成源映射的小而快的库; 其实它最主要的功能就是对一些源代码和庞大的AST字符串做轻量级字符串的替换; 在vite工具源码和vuecompilersfc中大量使用; 使用:importMagicStringfrommagicstring;constsnewMagicString(problems99);替换problemsanswers。overwrite(0,8,answer)s。toString()answer99生成sourcemapvarmaps。generateMap({source:source。js,file:converted。js。map,includeContent:true})复制代码8。fsextra fsextra是一个强大的文件操作库,是Nodejsfs模块的增强版; 这个就不多讲了,因为它在千锤百炼之下只能形容它是YYDS,查看更多官方文档。9。chokidar chokidar是一款专门用于文件监控的库;chokidar只在vite工具源码中有使用; 其实Node。js标准库中提供fs。watch和fs。watchFile两个方法用于处理文件监控,但是为什么我们还需要chokidar呢? 主要是由于兼容性不好、无法监听、监听多次等大量影响性能的问题; chokidar用法:constchokidarrequire(chokidar);constwatcherchokidar。watch(file,dir,glob,orarray,{ignored:(〔〕)。。,persistent:true});watcher。on(add,pathconsole。log(File{path}hasbeenadded))。on(change,pathconsole。log(File{path}hasbeenchanged))。on(unlink,pathconsole。log(File{path}hasbeenremoved))。on(addDir,pathconsole。log(Directory{path}hasbeenadded))。on(unlinkDir,pathconsole。log(Directory{path}hasbeenremoved))。on(error,errorconsole。log(Watchererror:{error}))。on(ready,()console。log(Initialscancomplete。Readyforchanges))。on(all,(event,path)console。log(event,path))。on(raw,(event,path,details){log(Raweventinfo:,event,path,details);});复制代码10。fastglob fastglob是一个快速批量导入、读取文件的库;fastglob只在vite工具源码中有使用; 基本语法::匹配除斜杆、影藏文件外的所有文件内容;:匹配零个或多个层级的目录;?:匹配除斜杆以外的任何单个字符;〔seq〕:匹配〔〕中的任意字符seq; 如何使用:constfgrequire(fastglob);constentriesawaitfg(〔。editorconfig,index。js〕,{dot:true});复制代码 在vite中使用: vite工具中import。meta。glob方法(如下)就是基于这个库来实现,所以如果你在自己的工具库中有批量文件等的操作,这个库是以很不错的选择;constmodulesimport。meta。glob(。dir。js,{query:{foo:bar,bar:true}})复制代码 vite通过fastglob工具把它生成如下代码vite生成的代码constmodules{。dirfoo。js:()import(。dirfoo。js?foobarbartrue)。then((m)m。setup),。dirbar。js:()import(。dirbar。js?foobarbartrue)。then((m)m。setup)}复制代码11。debug debug是一个模仿Node。js核心调试技术的小型JavaScript调试程序,在适用于Node。js和Web浏览器都可使用;debug只在vite工具源码中有使用; 说直白点就是你可以使用debug来对你的程序进行毫秒级别时间差的统计对你程序代码进行优化; 使用:vardebugrequire(debug)(http),httprequire(http),nameMyApp;fakeappdebug(bootingo,name);http。createServer(function(req,res){debug(req。methodreq。url);res。end(hello);})。listen(3000,function(){debug(listening);});fakeworkerofsomekindrequire(。worker);复制代码 如果你对你的代码或者自研的工具等有较高性能要求,强烈建议可以使用debug来进行调式。12。dotenv dotenv是一个零依赖模块,可将。env文件中的环境变量加载到process。env中;dotenv只在vite工具源码中有使用; 如何使用:创建。env文件S3BUCKETYOURS3BUCKETSECRETKEYYOURSECRETKEYGOESHERE复制代码使用importasdotenvfromdotenvdotenv。config()console。log(process。env)复制代码13。esbuild esbuild是一个基于Go语言开发的JavaScript打包工具,被Vite用于开发环境的依赖解析; 相比传统的打包工具,主打性能优势,在构建速度上可以快10100倍; 到现在知道为啥vite为啥快了吧,esbuild就是第一功臣。 优势:没有缓存机制也有极快的打包速度支持es6和cjs模块支持es6modules的treeshaking支持ts和jsxsourcemap压缩工具自定义的插件开发 使用: esbuild在API层面上非常简洁,主要的API只有两个:Transform和Build,这两个API可以通过CLI,JavaScript,Go的方式调用;transform:调用这个API能将ts,jsx等文件转换为js文件;cliexbuild。test。tsloaderts输出conststrHelloWorld;jsapi调用constesbuildrequire(esbuild);constfsrequire(fs);constpathrequire(path);constfilePathpath。resolve(dirname,test。ts);constcodeesbuild。transformSync(fs。readFilesync(filePath),{loader:ts,})console。log(code);输出{code:conststrHelloWorld,map:,warnings:〔〕}build:整合了transform后的代码,可以将一个或者多个文件转换并保存为文件;cliesbuildtest。tsoutfile。disttest。js{errors:〔〕,warnings:〔〕}jsapi调用constesbuildrequire(esbuild);constpathrequire(path);constresultesbuild。buildSync({entryPoints:〔path。resolve(dirname,test。ts)〕,outdir:path。resolve(dirname,dist),});console。log(result);{errors:〔〕,warnings:〔〕}14。rollup rollup是一个JavaScript模块打包器,可以将小块代码编译成大块复杂的代码,我们熟悉的vue、react、vuex、vuerouter等都是用rollup进行打包的。 在vite中的生产环境(Production)就是基于rollup打包来构建主要代码的。 使用:创建rollup。config。js文件配置文件exportdefault{input:srcindex。js,output:{name:amapUpper,file:distamapUpper。js,format:umd},plugins:〔〕};运行{scripts:{dev:rollupisrcindex。jsodistbundle。jsfes},}执行npmrundev15。ws ws是一个简单易用、速度极快且经过全面测试的WebSocket客户端和服务器实现;完全可以是Socket。io的替代方案;ws只在vite工具源码中有使用。 说直白一点就是通过ws,咱们可以实现服务端和客户端的长连接,且通过ws对象,就可以获取到客户端发送过来的信息和主动推送信息给客户端。 使用:server。jsconstWebSocketrequire(ws)constWebSocketServerWebSocket。Server;创建websocket服务器监听在3000端口constwssnewWebSocketServer({port:3000})服务器被客户端连接wss。on(connection,(ws){通过ws对象,就可以获取到客户端发送过来的信息和主动推送信息给客户端vari0varintsetInterval(functionf(){ws。send(i)每隔1秒给连接方报一次数},1000)})client。jsconstWebSocketrequire(ws)constwsnewWebSocket(ws:localhost:3000)接受ws。on(message,(message){console。log(message)当数字达到10时,断开连接if(message10){ws。send(close);ws。close()}})16。connect connect是一个最早期的HTTP服务器框架,亦可称为中间件插件;express就是基于此框架做的扩展; 注意:从vite2开始官方已从依赖koa转成connect了; 至于为什么使用connect而不是koa,咱们看官方的回答: 大概意思就是:由于大部分逻辑应该通过插件钩子而不是中间件来完成,因此对中间件的需求大大减少;所以使用connect优先级会高于Koa。17。esno esno是一个基于esbuild的TSESNext的Node。js运行时; 说直白点就是可以类似tsnode一样直接运行TS文件,那为甚么还用esno呢? 因为esno是基于esbuild运行的,esbuild有多快,上面我们有讲到了吧,这里就不复述了。 使用:{scripts:{start:esnoindex。ts},dependencies:{esno:}}复制代码npmrunstart复制代码18。tsup tsup是一个轻小且无需配置的,由esbuild支持的打包工具; 它可以直接把。ts。tsx转成不同格式esm、cjs、iife的文件,快速打包你的工具库; 使用:安装tsuppnpmitsupD在根目录下的package。json中配置{scripts:{dev:pnpmrunbuildwatchignorewatchexamples,build:tsupsrcindex。tsdtsformatcjs,esm},}19。vitepress vitepress是在vuepress的基础上实现的静态网站生成器,区别在于vitepress是建立在vite之上做的开发; 优势:基于vite而不是webpack,所有更快的启动时间,热重载等;使用vue3来减少js的有效负载; 所以如果你想写一个在线文档仓库,那么vitepress就是一个很好的选择。20。vitest vitest是一个由vite提供支持的快速单元测试框架。 优势:由Vite提供支持的极速单元测试框架。与Vite的配置通用,watch模式下极快的反应(相当于测试中HMR)。可以对VueReact组件进行测试。开箱即用TypescriptJSXESM(这一点我想配过jest的人应该懂是什么意思)与Jest几乎相同的API,同时也有Jest的快照功能(这个非常好用!)模拟DOM生成测试覆盖率ESM优先,顶级等待开箱即用的TypeScriptJSX支持套件和测试的过滤、超时、并发等等 所以你还有什么理由不使用vitest呢?其它 其实细心的同学可能会发现,目前vue3和vite3都是一个monorepo仓库,且都是使用pnpmworkspace来进行仓库管理的; 所以了解monorepo和pnpmworkspace对源码的阅读也是有很大的帮助的; 关于这块更多详细可以查看《如何入门vite源码》进行了解。 当然,上面的分享的工具库只是在源码中使用场景较多的库,还有一些库由于场景较少所以这里没有做详细的解释说明,如果您想了解源码中的哪个工具库,欢迎补充,取舍后我会做及时的更新;