首页/文章/vite工具

研究vite心得

2024-05-20
304711 分钟
...

vite作为我们前端开发工具利器,在开发时,作为开发服务器时提供极速的启动体验、调试接口时提供代理服务器功能,开发时提供HMR能力支持修改无感刷新,提供兼容rollup的打包生态,提供方便扩展的插件系统等等,这些是怎么做的呢,本文在学习了文档&源码后与大家探讨一下 vite 以下功能的实现思路:

  • 开发服务器
  • proxy代理
  • 预构建
  • hmr
  • 插件系统
  1. 浏览器原生支持 原生esm,当碰到 import 一个(非本地)模块时,浏览器会发一个请求(服务器收到请求后怎么处理都完全可控),如下:

  1. 熟悉使用vite-plugin-inspect插件,可以方便查看开发时的代码处理中间产物及最终返回

  2. nodejs 简单 http.createServer/express/koa demo基础,了解中间件

开发-服务器,其实就是一个简单的服务器,想一下express demo,能接收请求,自定义返回(这就为所欲为了啊);vite中直接用node:http/s启一个服务,用 connect 做中间件容器,处理浏览器的请求:

搜下 middlewares.use,主要的各种处理逻辑入口找到了:

其中主要负责处理文件请求的是transformMiddleware中间件,里面主要的逻辑是:【解析路径-resolve -> 加载文件-load -> 代码转译-transform(完全可控)】(这里会定好处理工作流,做插件系统,后面说到)-> 返回处理结果(主要返回浏览器支持的es6模块,不要被文件后缀名迷惑,浏览器是根据Content-Type响应头(可控)来处理响应的)

代理有正向代理和反向代理之分,代理客户端的是正向代理,代理服务器的是反向代理(不清楚的再问问ai)。

开发服务器配置代理主要是解决开发时前后端调试接口时碰到cors报错(欢迎指教),因为cors只会在浏览器上起作用,在服务端发请求没有效果。

vite用的代理是用http-proxy模块开启正向代理,简单demo如下:

vite 中代理逻辑主要在proxyMiddleware中间件里,用法如下(关注红圈部分):

在vite中也可以访问http-proxy实例(如下),在需要修改请求或响应头时有用,比如对接第三方时返回302重定向到location头,这时可以改写location头为开发环境地址。

看了下http-proxy源码,本质上就是从node端发http请求(用啥都行axios/fetch等等),http-proxy这里用的是 http 模块的request方法发起代理请求)

vite服务启动时先执行,在特定情况重新执行预构建,只在开发服务时执行。

原因:

  1. cjs转esm:把commonjs/umd模块的依赖转为esm模块
  2. 提高后续页面的加载性能:把具有多个依赖的esm依赖项打包成单个模块,例如 lodash-es

思路原理:

  1. 先找出依赖,并解析出依赖入口地址,一般是bare import,比如import { createApp } from "vue";这种:先从html入口开始,解析出bare import格式的导入,vite中是用esbuild.context打包来获取bare import的,因为打包过程会涉及解析所有关联的import语句,vite通过编写一个esbuil插件,用onResolve钩子,在打包过程中,用filter过滤出bare import,然后记录下来bare import 的解析结果信息(能提取到就行,你用正则匹配或者其他办法也行,关键要快);

模块解析:有多种模块解析算法,也可以看看typescript的介绍,vite的开发node服务器中应该是和nodejs一样

  1. 把依赖入口地址作为入口,bundle(打包)输出一个esm格式的文件:通过esbuild.build方法打包,format设置为'esm',bundle设置为true(这样会把入口引用的模块打包到产物中)等等,打包结果写到node_modules/.vite目录下
  2. 重写依赖的导入路径:通过 import-analysis 插件改写模块路径为真实路径

思路:

  1. 监听到变化的模块:用 chokidar
  2. 当一个模块更新时,找出需要更新的模块(找出热更新边界、例如导入该模块的模块也更新)
  3. 通知客户端更新模块
    1. 怎么通知:用websocket通知需要更新的模块的信息(能通知到就行,用啥不重要)
    2. 怎么更新:首先要发请求获取更新后的模块(客户端收到websocket通知就可以发请求啦,浏览器请求后会自动执行),然后我们来脑暴下更新的模块有哪几种情况,对于每一种情况需要怎么更新,下面以vue demo项目中的模块为例:
      1. js模块

        1. 有导出:这种情况需要更新导入该模块的模块
        2. 没有导出,导入运行即可:这种情况直接请求更新后的模块即可
      2. 资源文件:在vite中静态资源的import,一般会把静态资源的路径导出返回,这时更新导入该资源的模块即可

      3. sfc文件:这个模块更新是最重要的,因为上面的模块通常都是被sfc文件导入,而sfc文件会被编译为导出render函数的js模块,本身不会执行全局的逻辑,如下(关注红线框),那重新请求更新的模块后,还得应用才行

下面看看vite中是怎么应用sfc模块的更新:先随便改下文件保存,看下浏览器network里的新请求的initiator,这更新的路径就出来了,点进去定位到源码:

接下来打个断点,再随便改点东西保存,然后会发现流程和我们推想的差不多

  1. 第一步先发请求获取最新模块,这时模块代码会运行,通过import.meta.hot.accept注册回调(import.meta.hot.accept代码是vite-vue插件注入的)
  2. 第二步触发import.meta.hot.accept注册的回调,sfc组件的更新也就是在这里更新的

可以看到最终sfc最终是通过(__VUE_HMR_RUNTIME__.rerender(updated.__hmrId, updated.render);) 重渲染组件的(rerender函数在vue源码的runtime-core/src/hmr.ts里,最终通过调用update函数重渲染组件(如下截图)-> update()函数通过重新执行响应式effect来触发更新-> effect里实际运行的是componentUpdateFn函数,里面调用了patch执行更新(vdom diff过程))

在vite开发/构建过程中,某些特定时机触发的函数集合(钩子)(类比vue生命周期钩子,但不单单是切面独立的逻辑,插件钩子可接收特定的参数,并产生特定的结果影响最终结果)

要理解插件(钩子集),就要理解vite整体工作流水线,主体大概就是

  1. 起一个 开发-服务器(就是一个简单的服务器,想一下express demo,能接收请求,自定义返回),然后根据浏览器的请求信息(定好的格式)开始 -> 2.(解析路径resolve、加载文件 load、代码转译transform)(完全可控) ->
  2. 返回处理结果(浏览器支持的es6模块/资源,不要被文件后缀名迷惑,浏览器是根据Content-Type响应头(可控)来处理响应的);
  • 然后各种钩子就是作者在这个流水线中把有意义的点暴露出来,对于同一种钩子,可能有很多个,那么执行顺序呢,简单的话可以 按添加顺序-全部-执行,但根据钩子功能,也可以考虑异步-并行/串行,不全部-执行(比如解析路径的钩子,有结果就行,不需要全部执行)(如何管理不同的钩子和相同钩子的执行模式,Tapable就是专门提供插件钩子支持的)等等

同理的话,所有库插件的编写也如此,对于作者,最重要的是理清工作流水线(要怎么干),暴露好钩子;对于开发者,最重要的是理解工作流水线(是干什么的)

如果您觉得这篇文章有帮助,请点个赞吧~

分享文章

相关文章

更多文章 →
vite工具2026-03-17
深度解析:NODE_ENV 与 Mode (模式)
在现代前端开发中,尤其是使用 Vite 、 Qwik 、 Next.js 等基于 Node.js 的构建工具时,开发者经常会被两个相似的概念绕晕: 和 Mode (模式) 。 它们看起来都在做同一件事:“区分开发环境和生产环境”。但实际上,它们在架构设计中扮演着截然不同却又紧密协作的角色。混淆这两者可能导致构建配置错误、环境变量加载失败,甚至生产环境泄露敏感信息。 一、核心定义:它们到底是什么? 1\. :行业通用的“运行时开关” 起源...
学习
vite工具2025-10-01
vite常用配置
目录 1\. 基础配置 1.1 项目初始化 1.2 基础 vite.config.js 配置 配置说明与最佳实践 插件配置 (plugins) 好处 : 插件系统是Vite的核心特性,提供了丰富的功能扩展能力 坏处 : 过多插件会增加构建时间,插件冲突可能导致构建失败 建议 : 只引入必要的插件,定期检查插件更新和兼容性 适用场景 : 所有Vite项目都需要根据技术栈选择合适的插件 开发服务器配置 (server) host: ‘0.0...
学习
vite工具2025-06-04
Vite 项目中使用 vite-plugin-dts 插件的详细指南
在现代前端开发中,TypeScript 的类型声明文件( )对于提供良好的开发体验和代码提示至关重要。如果你正在使用 Vite 构建一个库项目, 插件是一个非常有用的工具,它可以帮助你自动生成 文件。以下是如何在你的 Vite 项目中安装、配置和使用 插件的详细指南。 一、插件介绍 是一个用于在 Vite 的库模式下,从 或 源文件生成类型文件( )的插件。它能够帮助开发者在构建库时,自动生成类型声明文件,从而提高开发效率。 二、安装插...
学习
vite工具2025-03-11
vite项目打包build后提示说超过500k了
说可以通过配置build.rollupOptions.output.manualChunks来提升一下,好可以,我来配置一下,把那些可能大的包单独分配一下: 然后再看一下,是变小了,但是还是500警告啊: 那就开始分析是哪个包比较大吧,使用rollup plugin visualizer这个插件来分析一下,rollup plugin visualizer是一个开源项目,地址: 安装: 配置插件 在 文件中添加 插件的配置,如下: 构建完...
学习
vite工具2024-10-10
一次低端机 WebView 白屏的兼容之路
问题 项目:Vite4 + Vue3,APP WebView 项目 页面在 OPPO A5 手机上打不开,页面空白。 最开始是客户端在看,然后发现一个警告,大概也因为没看出什么问题,给到 Web 前端。 相关背景 为了方便描述过程的行为,先做一些相关背景的介绍。知道这些背景才能更好的了解问题的复杂。这些在解决问题的过程中始终是干扰因素,在反复调试试错的过程中才梳理总结出来,这里把它们列出来。 使用测试 App,其中有两个入口,一个是本地...
学习
vite工具2024-09-09
推荐工具vite-plugin-fake-server,可线上部署使用mockmock线上部署
最近遇到了个麻烦,后端迟迟给不了接口,测试那边又要求数据不能写死,必须可以提供mock调试。这不最近找到了一个mock工具,能解决传统mock工具无法线上部署的问题。 工具名字叫做 ,兼容vite,从官网示例上来看是同时支持 和 来模拟数据的。使用起来也非常简单,分三步走就行。 1. 安装 2. 引入 这里贴出最简单的配置,一个是制定文件夹,一个是设置在生产环境下模拟数据。 3. 使用 这里我根据个人习惯,在 文件夹下创建一个 和数个模...
学习

评论

请登录后发表评论

去登录
加载评论中...