Appearance
7. 路径解析与静态资源
我们已经知道,Vite 的 transform 中间件负责编译源码。但它的工作远不止于此。当它在 main.js 中遇到 import App from './App.vue' 时,它还必须回答一个关键问题:这个 ./App.vue 到底在哪里?
浏览器本身是无法理解这种相对路径的。它需要一个绝对的 URL,比如 /src/App.vue,才能发起有效的请求。将模块导入语句中的“描述性路径”转换为浏览器可识别的“URL”的过程,就是路径解析(Path Resolution)。
Vite:一位经验丰富的“邮递员”
你可以把 Vite 的路径解析能力想象成一位经验丰富的邮递员。
相对路径 (
./App.vue):就像你给邻居写信,地址只写“隔壁”。邮递员(Vite)看到这封信是从你家发出的,他立刻就知道“隔壁”指的是你家旁边的房子,并能准确投递。别名路径 (
@/components/Button.vue):就像你在信封上写“去市中心最大的那个商场”。邮递员的脑子里有一张地图(resolve.alias配置),他知道“市中心最大的商场”对应的真实地址是“人民路 1 号”,于是就能把信送到正确的地方。裸模块路径 (
import React from 'react'):就像你在信上写“寄给‘React’这个人”。邮递员知道“React”是一个大名人,不住在普通的居民区,而是住在“node_modules名人社区”。他会把这个地址特殊处理,确保信件能送到node_modules/react手中。
Vite 的路径解析器,就是在 transform 过程中,将这些千奇百怪的“地址”一一翻译成浏览器可以理解的、以 / 开头的标准 URL。
这个过程通常发生在插件内部。例如,当 esbuild 插件处理一个 .ts 文件时,它会扫描所有的 import 语句,对每个导入路径执行解析逻辑,然后用解析后的 URL 替换掉原始路径。
javascript
// 转换前 (main.js)
import App from './App.vue';
// 转换后,返回给浏览器的代码
import App from '/src/App.vue';正是这个看似简单的重写步骤,构成了 Vite 按需加载的基石,让浏览器能够顺着一个模块,不断请求下一个模块。
public 目录:一个“法外之地”
在 Vite 项目的根目录下,通常有一个 public 目录。这是一个非常特殊的地方,我们可以称之为“法外之地”。
放在 public 目录下的文件,遵循一套完全不同的规则:
它们永远不会被处理:Vite 的
transform中间件会完全忽略public目录。这里面的文件不会被编译、打包,也不会被写入模块图。它们会被原封不动地复制到构建后的dist目录中。它们永远通过根路径 (
/) 访问:无论你在代码的哪个角落,都可以通过绝对路径/来引用public目录下的资源。例如,放在public/img/logo.png的图片,在任何组件中都可以通过<img src="/img/logo.png">来访问。
什么时候应该使用 public 目录?
文件名必须固定不变的文件:例如
robots.txt、favicon.ico或者manifest.webmanifest。这些文件需要被搜索引擎或浏览器直接通过固定的 URL 访问。你不想或不能导入的资源:例如,一个非常大的 3D 模型文件,或者一个第三方脚本,你只想通过一个简单的 URL 来引用它,而不是让它参与到 Vite 的模块化构建流程中。
兼容性代码:当你需要引入一个不支持 ES 模块的老旧 JS 库时,可以把它放在
public目录下,然后通过<script>标签在index.html中引入。
一句话总结:当一个资源需要脱离 Vite 的模块化系统,作为一个独立的、可通过根路径直接访问的静态文件时,就应该把它放在 public 目录。
理解了路径解析和 public 目录的规则,你就掌握了 Vite 处理项目中各类资源的完整逻辑。无论是需要编译的源码,还是无需处理的静态文件,Vite 都有清晰、高效的策略来应对。
到目前为止,我们已经了解了服务器如何启动、如何处理请求。但还有一个关键环节:当文件发生变化时,Vite 是如何感知到并触发 HMR 的呢?下一章,我们将揭晓答案。