关注vuejs作者的码农应该都知道,最近尤雨溪有了新宠vite,通过他在视频中分享vite的神情,可以感受到他对vite的钟爱。
vite 是什么呢?
vite 是一个由原生ESM驱动的非打包开发服务器,其作用类似webpack + webpack-dev-server,在github上d的第一次提交在2020年4月21日,但star数已经接近一万。
可以说,这是一个很新的工具,目前还没发布正式版,从近期的提交频率来看,应该很快就发布正式版了。
由于Vite是原生ESM的,因此他爸在视频说谈到,在上线部署时,也实现了类似rollup这个基于ES2015的打包功能,因此vite也是基于ES2015的JS打包工具,比Webpack和Browserify等使用CommonJS模块机制更高效,打包的文件体积更小,还支持相对路径。
为何推出vite?
vue3 beta版本出来了,万众期待尤雨溪快点发布vue3的正式版,他应该马不停蹄的开发vue3及其官方工具才对,为何又像开始vue3之前先整了半年多的 vue-cli 那样,在发布之前,要整了一下开发服务器呢?
在前手淘前端负责人winter采访尤雨溪视频中,他提到,起因是最近需要写大量的vue3相关的文档,使用之前基于 webpack 的vuepress写文档的框架,效率太低,于是他就自己单独搞了一个vite开发工具,且开源了基于vite的vitepress文档开发框架。
同时,基于vite的vue项目,在不使用webpack等打包工具的条件下,可以直接在浏览器运行请求的vue文件,因为面向现代浏览器,使用vite基于原生模块系统直接实现按需编译就可以了,而在webpack则需要将进行的编译放到内存中,打包所有文件。
vue3 的目标就是更快,在脚手架集成了 vite 以后,开发时就不用像webpack-dev-server那样,等很久才能渲染初页面了,而是启动后瞬间就有,再配上rollup 进行打包,基于vue3开发新项目,不仅性能更好,也会大大提升开发效率。
vite vs rollup vs webpack
前两年,大神有传言,库开发推荐用Rollup,应用开发推荐用Webpack,但是现在二者的功能差异小,Rollup也有热更新,Webpack也支持Tree shaking,而且都有强大的插件开发功能,他们更多的区别只是在写法上。
从 vite 的源码中可以看到,虽然Rollup也有热更新插件nollup,但是vite的单独实现了一套基于纯ESM的热更新,所以开发时单独用vite即可,而打包时则是单独使用rollup。
尤雨溪在视频中也提到,一个基于vite的全新脚手架create-vite-app也已经开源了,借助vue的强大生态,vite 必火,所以很有必要深入学习一下。
不过,在github上vitejs下面的项目只有四个,其中还有两个是面向react开发的,基于vite开发vue或react项目,还有很多坑需要填,对应的一些处理插件还没有rollup 和 webpack 丰富和完善。
另外,vite这个项目最后的打包还是用的rollup,或许某一天它会用自己开发自己。
vite的原理
因为我之前在外企工作过,习惯了直接看源码和英文文档,所以再我得知了vite后,马上去其源码仓库github.com/vitejs瞟了一眼,共有四个相关的项目:
- vite
- vite-plugin-react-pages
- vite-plugin-react
- create-vite-app
其中 vite 是核心库,而 create-vite-app 是开发的脚手架工具,取名很像create-react-app,通过集成vite-plugin-react-pages 和 vite-plugin-react,vite 也能开发react 项目。
由此看出,小右野心不小啊,想让 vite 和 webpack 一较高下的意图很明显。我们再看vite的package.json文件:
"dependencies": {
"@babel/parser": "^7.9.4",
"@rollup/plugin-commonjs": "^14.0.0",
"@rollup/plugin-json": "^4.0.3",
"@rollup/plugin-node-resolve": "^8.4.0",
"@types/koa": "^2.11.3",
"@types/lru-cache": "^5.1.0",
"@vue/compiler-dom": "^3.0.0-rc.5",
"@vue/compiler-sfc": "^3.0.0-rc.5",
"brotli-size": "^4.0.0",
"chalk": "^4.0.0",
"chokidar": "^3.3.1",
"clean-css": "^4.2.3",
"debug": "^4.1.1",
"dotenv": "^8.2.0",
"dotenv-expand": "^5.1.0",
"es-module-lexer": "^0.3.18",
"esbuild": "^0.6.10",
"etag": "^1.8.1",
"execa": "^4.0.1",
"fs-extra": "^9.0.0",
"hash-sum": "^2.0.0",
"isbuiltin": "^1.0.0",
"koa": "^2.11.0",
"koa-conditional-get": "^2.0.0",
"koa-etag": "^3.0.0",
"koa-proxies": "^0.11.0",
"koa-send": "^5.0.0",
"koa-static": "^5.0.0",
"lru-cache": "^5.1.1",
"magic-string": "^0.25.7",
"merge-source-map": "^1.1.0",
"mime-types": "^2.1.27",
"minimist": "^1.2.5",
"open": "^7.0.3",
"ora": "^4.0.4",
"postcss": "^7.0.28",
"postcss-discard-comments": "^4.0.2",
"postcss-import": "^12.0.1",
"postcss-load-config": "^2.1.0",
"resolve": "^1.17.0",
"rollup": "^2.20.0",
"rollup-plugin-dynamic-import-variables": "^1.0.1",
"rollup-plugin-terser": "^5.3.0",
"rollup-plugin-vue": "^6.0.0-beta.10",
"rollup-plugin-web-worker-loader": "^1.3.0",
"rollup-pluginutils": "^2.8.2",
"selfsigned": "^1.10.7",
"slash": "^3.0.0",
"vue": "^3.0.0-rc.5",
"ws": "^7.2.3"
},
可以看到其核心库主要有:
"vue": "^3.0.0-rc.5",
"rollup": "^2.20.0",
"koa": "^2.11.0",
"koa-proxies": "^0.11.0",
"koa-static": "^5.0.0",
进入项目看其他源码,可以知道,开发时,vite使用Koa构建的服务端,在createServer中主要通过中间件注册相关功能,提供一个web server 去代理 浏览器通过 http 请求的模块。
vue模块安装在node_modules中,浏览器ES Module是无法直接获取到项目下node_modules目录中的文件,其过程如下:
- 通过 koa 中间件获取请求 body
- 使用 es-module-lexer 解析资源 ast
- 获取 import 的内容后,判断资源是否是绝对路径,绝对视为 npm 模块
- 返回处理后的路径给浏览器,例如:"vue" => "/@modules/vue"
基于vite的项目中,在需要某个模块时动态引入,而不是提前打包,自然更快,不同于webpack等,不管某个模块是否用到,都会把所有的模块都提前打包进bundle中,随着项目越来越大,打包文件也越来越大,自然越来越慢。
前面提到,vite自己实现了一套热更新,其原理为:
- 在 server 端编译资源,然后推送新资源给 client ;
- client 收到资源信息,执行框架 rerender 逻辑;
- server 端 基于 watcher 监听文件改动,根据类型判断是js还是vue reload;
- 同时 client 端,Websocket监听了一些更新的消息类型,然后分别处理:
- 通过解析器拿到当前文件,并与缓存里的上一次解析结果进行比较,若有变化则render;
到此为止,我们发现,虽然package.json文件中引入了若干rollup相关的库,在开发时,都没有用到,rollup 只有在打包发布vite这个库时才用到。
通过create-vite-app/template-vue/package.json文件中的scripts 模块,我们看到了打包的命令:
"scripts": {
"dev": "vite",
"build": "vite build"
},
我们进一步看 vite build 执行的相关源码,发现打包时的各种处理确实都是vite自己实现的,一点也没用到rollup。
小结
随着vue3 正式版即将发布,vite 正式版也会同步跟进,相信很快我们就能基于 vue3 + vite 开发和上线正式的项目了,不过即使正式版还没发布,过两天我也会基于一个webpack4+vue3 的项目,调整为vite+vue 打包上线部署一下,对比一下两者的性能。
回到正题,虽然vite看似很不错,但是webapck5也已经来了,就像yarn和npm一样,在npm感受到了yarn的挑战后,也加快了对新特性的支持,以至npm和yarn 最新版本的功能越来越像,webapck和rollup也一定会在新版本中借鉴vite的一些特性。
所以,之后基于可能出现vite,webpack和rollup三足鼎立的发展趋势。
如果觉得不错,就点个赞,并转发一下哈~,