详解vite原理
创始人
2024-05-29 19:22:04
0次

背景

自从尤大大的 vite 问世后,现在前端的构建工具由 webpack 转向 vite 的越来越多,今天主要来讨论一下 vite 的一些工作原理,讨论之前大家可以看这篇文章,尤其是注意其中谈到的 Bundleless,这样也能更好的理解 vite。
前端构建工具大盘点:gulp、webpack、vite、rollup、esbuild、snowpack、babel、parcel、swc、tsc

毫无疑问,由于 EMS 的出现,Bundleless 是未来的趋势,而 vite 基本上是 Bundleless 的一个代表。

两种模式

Vite分为开发模式和生产模式

开发模式

Vite提供了一个开发服务器,然后结合原生的ESM,当代码中出现import的时候,发送一个资源请求,Vite开发服务器拦截请求,根据不同文件类型,在服务端完成模块的改写(比如单文件的解析编译等)和请求处理,实现真正的按需编译,然后返回给浏览器。请求的资源在服务器端按需编译返回,完全跳过了打包这个概念,不需要生成一个大的bundle。服务器随起随用,所以开发环境下的初次启动是非常快的。而且热更新的速度不会随着模块增多而变慢,因为代码改动后,并不会有bundle的过程。

Vite Server 所有逻辑基本都依赖中间件实现。这些中间件,拦截请求之后,完成了如下内容:

  • 处理 ESM 语法,比如将业务代码中的 import 第三方依赖路径转为浏览器可识别的依赖路径;
  • 对 .ts、.vue 等文件进行即时编译;
  • 对 Sass/Less 的需要预编译的模块进行编译;
  • 和浏览器端建立 socket 连接,实现 HMR。

在这里插入图片描述

生产模式

利用Rollup来构建源代码。
Vite将需要处理的代码分为了两大类

第三方依赖:
这类代码大部分都是纯JavaScript,而且不会怎么经常变化,Vite会通过pre-bundle的方式来处理这部分代码。Vite2使用esbulid来构建这部分代码,esbuild是基于go的,处理速度会比用JavaScript写的打包器要快10-100倍,这也是Vite为什么在开发阶段很快的一个原因。

业务代码:
通常这部分代码,都不是纯的JavaScript(例如:JSX,Vue等),经常会被修改,而且也不需要一次性全部加载(可以根据路由,做代码分割加载)
由于Vite使用了原生的ESM,Vite本身只需要按需编译代码,启动静态服务器就可以。只有当浏览器请求这些模块,这些模块才会被编译,动态加载到当前页面中。

热更新原理

就是在客户端与服务端建立了一个 websocket 连接,当代码被修改时,服务端发送消息通知客户端去请求修改模块的代码,完成热更新。

其他优化

缓存
https://cn.vitejs.dev/guide/dep-pre-bundling.html#caching

  • Vite会将pre-bundle的依赖存放在 node_modules/.vite 下,如果想修改目录,可以在 vite 文档中搜索 cacheDir
    在这里插入图片描述
  • 浏览器缓存 Vite Dev Server 会将这些第三方依赖设置HTTP强缓存来提升性能,只有当这些依赖发生变化时,才会去更新query id使之前的的缓存失效。

使用esbuild依赖预构建
依赖预构建仅会在开发模式下应用,并会使用 esbuild 将依赖转为 ESM 模块。在生产构建中则会使用 @rollup/plugin-commonjs。
https://cn.vitejs.dev/guide/dep-pre-bundling.html#dependency-pre-bundling

Q&A

为什么生产环境还是需要bundle?
尽管原生 ESM 现在得到了广泛支持,但由于嵌套导入会导致额外的网络往返,在生产环境中发布未打包的 ESM 仍然效率低下(即使使用 HTTP/2)。为了在生产环境中获得最佳的加载性能,最好还是将代码进行 tree-shaking、懒加载和 chunk 分割(以获得更好的缓存)。

为何不用 ESBuild 打包?
虽然 esbuild 快得惊人,并且已经是一个在构建库方面比较出色的工具,但一些针对构建 应用 的重要功能仍然还在持续开发中 —— 特别是代码分割和 CSS 处理方面。就目前来说,Rollup 在应用打包方面更加成熟和灵活。尽管如此,当未来这些功能稳定后,我们也不排除使用 esbuild 作为生产构建器的可能。

参考

https://cn.vitejs.dev/guide/why.html

相关内容

热门资讯

前端-session、jwt 目录:   (1)session (2&#x...
linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
nodejs:本地安装nvm实... 一、背景-使用不同版本node的原因 vue3+ts、nuxt3版本,node...
JAVA集合知识整理 Java集合知识整理 HashMap相关 HashMap的底层数据结构:jdk1.8之...
无刷直流电机介绍及单片机控制实... 无刷直流电机介绍及单片机控制实例前言基本概念优势与劣势使用寿命基本结构使用单片机控制实例电子调速器&...
fwdiary(2) dp2 1.传纸条  AcWing 275. 传纸条 - AcWing 走两条路,走一条最大的...
常用的DOS命令 常用的DOS命令 DOS(Disk Operating System,磁...
<C++> 类和对象(下) 1.const成员函数将const修饰的“成员函数”称之为const成员函数,cons...