Skip to content
微信公众号

Vite

Vie是vue的作者尤雨溪在开发vue3.0的时候开发的一个web开发构建工具。由于其原生ES模块导入方式,可以实现闪电般的冷服务器启动。Vite是一种新型前端构建工具,能够显著提升前端开发体验。它主要由两部分组成:

  • 一个开发服务器,它基于 原生 ES 模块 提供了 丰富的内建功能,如速度快到惊人的 模块热更新(HMR)。
  • 一套构建指令,它使用 Rollup 打包你的代码,并且它是预配置的,可输出用于生产环境的高度优化过的静态资源。

Vite意在提供开箱即用的配置,同时它的插件API和JavaScript API带来了高度的可扩展性,并有完整的类型支持。

vite创建的项目开发依赖非常简单,只有vite和@vue/compiler-sfc。

vite项目提供了两个子命令vite serve和vite build。

vite serve开启一个用于开发的web服务器,在启动服务器的时候不需要编译所有的代码文件,启动速度很快。

而vue-cli启动项目的时候使用vue-cli-service serve,它内部会先用webpack打包模块,如果模块比较多,打包速度会变慢,把打包的结果存储在内存中,然后开启web服务器供浏览器访问。

vite利用现代浏览器支持的ES Module模块化的特性,省略了对模块的打包。对于需要编译的组件,例如单文件组件、样式模块等,vite采用即时编译,就是说具体请求某个文件的时候才会在服务端编译这个文件,这种即时编译的好处就是按需编译,速度会更快。

vite也支持HMR,相比webpack更好,webpack HMR会自动以这个文件为入口重新build一次,所有涉及的依赖也都会被加载一遍,而Vite HMR是立即编译当前所修改的文件。

vite在生产中使用vite build命令,这个命令内部采用rollup进行打包,最终还是会把文件提前编译并打包到一起。对于代码分割,vite内部使用原生的动态导入的特性实现的,所以打包结果只支持现代浏览器。

vite出现引起了一个疑问,有没有必要打包应用?之前使用webpack打包,会把所有的模块打包到bundle.js中,这里有两个原因,一个是浏览器环境并不支持模块化,另一个是零散的模块文件会产生大量的HTTP请求。这两个问题目前都有所解决,第一个浏览器支持ES Module模块化,第二个大量HTTP请求可以使用HTTP2来复用连接。

vite核心原理模拟

web服务器模拟,先安装koa和koa-send,然后编写执行脚本

js
#!/usr/bin/env node
const koa = require('koa')
const send = require('koa-send')

const app = new Koa()

//1. 静态文件服务器
app.use(async (ctx,next)=>{
    await send(ctx,ctx.path,{root:process.cwd(),index: 'index.html'})
    await next()
})

app.listen(3000)
console.log('Server running @ http://localhost:3000')

ESBuild

ESBuild是基于Go语言开发的JavaScript Bundler,它的构建速度是webpack的几十倍。由Figma前CTO Evan Wallace开发,并且也被Vite用于开发环境的依赖解析和Transform。

实现原理

  • 由Go实现并编译成本地代码:多数Bundler都是由JavaScript实现的,但是CLI应用对于JIT编译语言来说是性能表现最不好的。每次运行Bundler的时候,JS虚拟机都是以第一次运行代码的视角来解析Bundler(比如Webpack)的代码,没有优化信息。当ESBuild在解析JavaScript的时候,Node还在解析Bundler的JS代码。
  • 重度使用并行计算:Go语言本身的设计就很重视并行计算,所以ESBuild对这一点会加以利用。在构建中主要由三个环节:解析(Parsing),链接(Linking)和代码生成(Code generation)。在解析和代码生成环节会尽可能使用多核进行并行计算。
  • ESBuild中的一切代码从零实现:通过自行实现所有逻辑来避免第三方库带来的性能问题,统一的数据结构可以减少数据转换开销,并且可以根据需要改变架构,当然最大的缺点就是工作量倍增。
  • 对内存的高校使用:ESBuild在实现时尽量减少数据的传递以及数据的转换,ESBuild尽量减少对整体AST的传递,并且尽可能复用AST数据,其他的Bundler可能会在编译的不同阶段往复转换数据格式(string->TS->JS->older JS->string....),在内存存储效率方面Go也比JavaScript更高效。

使用方式

  1. 全局安装Esbuild命令,安装完成后可以通过esbuild --version查看版本号
shell
npm install esbuild -g
  1. 创建文件,添加测试文件
js
//index.js
const {cloneDeep} = 'lodash'
console.log(cloneDeep);
  1. 执行构建命令
shell
esbuild ./index.js --bundle --outfile=out_esb.js --minify
  1. 查看构建后的文件

优缺点

优点:

  • Golang开发:采用Go语言开发,可以充分利用多线程打包,并且线程之间共享内容,直接编译成机器码,大大节省了程序运行时间。
  • 多核并行:得益于Go当中多线程共享内存的优势,内部打包算法充分利用多核CPU优势
  • 从零造轮子:没有任何第三方库的黑盒逻辑,保证极致的代码性能
  • 高效利用内存:Esbuild中从头到尾尽可能地复用一份AST节点数据,从而大大提高了内存的利用效率,提升编译性能

缺点:

  • 没有TS类型检查
  • 不能操作AST
  • 不支持装饰器语法
  • 产物target无法降级到ES5及以下

SWC

SWC是一个用Rust写的高性能TypeScript/JavaScript转译器,类似于babel。是基于Rust的JavaScript Compiler(其生态中也包含打包工具spack),目前为NextJS/parcel/Deno等前端圈知名项目使用。

实现原理

参考文档:https://zhuanlan.zhihu.com/p/437529362

本站总访问量次,本站总访客数人次
Released under the MIT License.