Appearance
6. 中间件管线与请求处理
当 Vite 开发服务器成功启动后,它就开始了核心的使命:监听并处理来自浏览器的 HTTP 请求。Vite 在这方面的工作方式,非常像一个高度自动化的“包裹分拣中心”。
这个分拣中心的核心,就是一套基于 connect 库构建的中间件管线(Middleware Pipeline)。
包裹分拣中心:Connect 与中间件
connect 是一个 Node.js 中间件框架,你可以把它想象成一个可插拔的、链式的处理系统。每个中间件都是一个独立的“处理站”,负责一项特定的任务。
当一个请求(包裹)进入分拣中心时,它会:
- 从第一个处理站开始。
- 如果当前处理站能处理这个包裹(例如,这是一个图片请求,而当前是“静态资源处理站”),它就会处理该包裹,然后直接把它发走(响应请求),旅程结束。
- 如果当前处理站不能处理,或者处理完后觉得还需要其他处理,它就会调用
next()函数,把包裹传递给链条上的下一个处理站。
Vite 精心安排了一系列中间件,形成了一条高效的流水线,来处理前端开发中遇到的各种请求。
Vite 的核心中间件之旅
一个典型的 HTTP 请求,例如浏览器请求 /src/main.ts,在 Vite 的中间件管线中会经历一场怎样的旅行呢?
让我们跟随这个请求,走一遍核心的流程:
1. base 中间件
- 职责:处理
config.base选项。 - 工作:如果你的
vite.config.js中设置了base: '/my-app/',那么所有资源的 URL 都会带上这个前缀。这个中间件的作用就是检查请求的 URL 是否以/my-app/开头,如果不是,它就不会处理;如果是,它会把这个前缀“剥离”,还原成项目内的真实路径(例如,将/my-app/src/main.ts变为/src/main.ts),然后再交给后续的中间件处理。
2. htmlFallback 中间件
- 职责:处理 HTML5 History API 的路由回退。
- 工作:在单页应用(SPA)中,当我们访问
/about这样的路由时,服务器上并没有一个真实的/about文件。这个请求应该回退到index.html,由前端路由来接管。这个中间件就是做这件事的。如果一个请求看起来像是一个页面导航,但服务器上又找不到对应的文件,它就会把请求重写到index.html。
3. transform 中间件(核心中的核心)
- 职责:编译和转换项目源码。
- 工作:这是 Vite 的魔法发生的核心地带。当
/src/main.ts这个请求来到这里时:- 它首先会检查 URL,判断这是一个需要转换的源码文件(而不是一个普通的静态资源)。
- 它会读取
main.ts的文件内容。 - 然后,它会调用插件容器(
pluginContainer),让注册的插件对代码进行“接力转换”。例如,@vitejs/plugin-vue会处理.vue文件,esbuild会处理.ts文件。 - 在转换过程中,它会分析代码的依赖(
import),并更新模块图(moduleGraph)。 - 最后,它会将转换后的 JavaScript 代码返回给浏览器。
4. static 中间件
- 职责:提供静态资源服务。
- 工作:如果一个请求成功“幸存”到这一步,例如它是一个对
/logo.png或/assets/style.css的请求,那么transform中间件会跳过它。此时,static中间件(通常由serve-static库实现)就会接手。它会在public目录和项目的根目录中寻找对应的文件。如果找到了,就直接将文件内容返回给浏览器。这是最传统、最简单的文件服务。
顺序至关重要
Vite 中间件的注册顺序是经过精心设计的,这保证了最高效的处理路径。
- 高频、普适的在前:例如,
base处理和htmlFallback几乎对所有请求都可能生效,所以放在前面。 - 核心转换在中间:
transform中间件是处理源码的核心,它位于中间,负责处理那些需要“深度加工”的请求。 - 兜底的在最后:
static中间件作为最后的防线,处理那些不需要任何转换的普通文件请求。
通过这样一条有序的、各司其职的中间件管线,Vite 将复杂的请求处理逻辑拆解得清晰而高效。理解了这条管线,你就理解了 Vite 开发服务器的“神经中枢”。
在下一章,我们将继续深入,探讨 Vite 是如何解析路径,以及如何处理 public 目录下的静态资源的。