Skip to content

6. 中间件管线与请求处理

当 Vite 开发服务器成功启动后,它就开始了核心的使命:监听并处理来自浏览器的 HTTP 请求。Vite 在这方面的工作方式,非常像一个高度自动化的“包裹分拣中心”。

这个分拣中心的核心,就是一套基于 connect 库构建的中间件管线(Middleware Pipeline)

包裹分拣中心:Connect 与中间件

connect 是一个 Node.js 中间件框架,你可以把它想象成一个可插拔的、链式的处理系统。每个中间件都是一个独立的“处理站”,负责一项特定的任务。

当一个请求(包裹)进入分拣中心时,它会:

  1. 从第一个处理站开始。
  2. 如果当前处理站能处理这个包裹(例如,这是一个图片请求,而当前是“静态资源处理站”),它就会处理该包裹,然后直接把它发走(响应请求),旅程结束。
  3. 如果当前处理站不能处理,或者处理完后觉得还需要其他处理,它就会调用 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 这个请求来到这里时:
    1. 它首先会检查 URL,判断这是一个需要转换的源码文件(而不是一个普通的静态资源)。
    2. 它会读取 main.ts 的文件内容。
    3. 然后,它会调用插件容器(pluginContainer,让注册的插件对代码进行“接力转换”。例如,@vitejs/plugin-vue 会处理 .vue 文件,esbuild 会处理 .ts 文件。
    4. 在转换过程中,它会分析代码的依赖(import),并更新模块图(moduleGraph
    5. 最后,它会将转换后的 JavaScript 代码返回给浏览器。

4. static 中间件

  • 职责:提供静态资源服务。
  • 工作:如果一个请求成功“幸存”到这一步,例如它是一个对 /logo.png/assets/style.css 的请求,那么 transform 中间件会跳过它。此时,static 中间件(通常由 serve-static 库实现)就会接手。它会在 public 目录和项目的根目录中寻找对应的文件。如果找到了,就直接将文件内容返回给浏览器。这是最传统、最简单的文件服务。

顺序至关重要

Vite 中间件的注册顺序是经过精心设计的,这保证了最高效的处理路径。

  • 高频、普适的在前:例如,base 处理和 htmlFallback 几乎对所有请求都可能生效,所以放在前面。
  • 核心转换在中间transform 中间件是处理源码的核心,它位于中间,负责处理那些需要“深度加工”的请求。
  • 兜底的在最后static 中间件作为最后的防线,处理那些不需要任何转换的普通文件请求。

通过这样一条有序的、各司其职的中间件管线,Vite 将复杂的请求处理逻辑拆解得清晰而高效。理解了这条管线,你就理解了 Vite 开发服务器的“神经中枢”。

在下一章,我们将继续深入,探讨 Vite 是如何解析路径,以及如何处理 public 目录下的静态资源的。

6. 中间件管线与请求处理 has loaded