依赖预构建
当你第一次运行 vite
时,Vite 会在本地加载你的站点之前预构建你的项目依赖。默认情况下,此过程会自动且透明地进行。
原因
这是 Vite 执行我们所说的“依赖预构建”。此过程有两个目的
CommonJS 和 UMD 兼容性:在开发过程中,Vite 的开发服务器会将所有代码作为原生 ESM 提供服务。因此,Vite 必须首先将以 CommonJS 或 UMD 格式提供的依赖项转换为 ESM。
在转换 CommonJS 依赖项时,Vite 会执行智能导入分析,以便即使导出是动态分配的(例如 React),对 CommonJS 模块的命名导入也能按预期工作。
js// works as expected import React, { useState } from 'react'
性能:Vite 将具有许多内部模块的 ESM 依赖项转换为单个模块,以提高后续页面加载性能。
某些包将其 ES 模块构建为许多相互导入的单独文件。例如,
lodash-es
拥有超过 600 个内部模块!当我们执行import { debounce } from 'lodash-es'
时,浏览器会同时发出 600 多个 HTTP 请求!即使服务器能够轻松处理这些请求,但大量请求也会导致浏览器端网络拥塞,从而导致页面加载速度明显变慢。通过将
lodash-es
预构建成单个模块,我们现在只需要一个 HTTP 请求即可!
注意
依赖预构建仅适用于开发模式,并使用 esbuild
将依赖项转换为 ESM。在生产构建中,则使用 @rollup/plugin-commonjs
代替。
自动依赖发现
如果找不到现有的缓存,Vite 将遍历你的源代码并自动发现依赖项导入(即期望从 node_modules
解析的“裸导入”),并将这些找到的导入用作预构建的入口点。预构建使用 esbuild
执行,因此通常非常快。
服务器启动后,如果遇到缓存中不存在的新依赖项导入,Vite 将重新运行依赖项构建过程,并在需要时重新加载页面。
单仓库和链接依赖
在单仓库设置中,依赖项可能是来自同一仓库的链接包。Vite 会自动检测未从 node_modules
解析的依赖项,并将链接依赖项视为源代码。它不会尝试构建链接依赖项,而是会分析链接依赖项的依赖项列表。
但是,这要求链接依赖项导出为 ESM。如果不是,你可以将依赖项添加到 optimizeDeps.include
和 build.commonjsOptions.include
中的配置。
export default defineConfig({
optimizeDeps: {
include: ['linked-dep'],
},
build: {
commonjsOptions: {
include: [/linked-dep/, /node_modules/],
},
},
})
在修改链接依赖项时,请使用 --force
命令行选项重新启动开发服务器,以使更改生效。
自定义行为
默认的依赖项发现启发式方法可能并不总是理想的。在需要显式包含/排除依赖项列表的情况下,请使用 optimizeDeps
配置选项。
optimizeDeps.include
或 optimizeDeps.exclude
的一个典型用例是,当你的导入在源代码中无法直接发现时。例如,导入可能是插件转换的结果。这意味着 Vite 无法在初始扫描中发现导入 - 它只能在浏览器请求文件并进行转换后才能发现它。这将导致服务器在服务器启动后立即重新构建。
include
和 exclude
都可以用来处理这种情况。如果依赖项很大(具有许多内部模块)或为 CommonJS,则应将其包含在内;如果依赖项很小且已经是有效的 ESM,则可以将其排除,并让浏览器直接加载它。
你还可以使用 optimizeDeps.esbuildOptions
选项进一步自定义 esbuild。例如,添加一个 esbuild 插件来处理依赖项中的特殊文件或更改 构建 target
。
缓存
文件系统缓存
Vite 将预构建的依赖项缓存到 node_modules/.vite
中。它根据以下几个来源确定是否需要重新运行预构建步骤
- 包管理器锁定文件内容,例如
package-lock.json
、yarn.lock
、pnpm-lock.yaml
或bun.lockb
。 - 补丁文件夹修改时间。
- 如果存在,则为
vite.config.js
中的相关字段。 NODE_ENV
值。
仅当上述内容之一发生更改时,才需要重新运行预构建步骤。
如果出于某种原因,你想要强制 Vite 重新构建依赖项,则可以启动带有 --force
命令行选项的开发服务器,或手动删除 node_modules/.vite
缓存目录。
浏览器缓存
已解析的依赖项请求使用 HTTP 标头 max-age=31536000,immutable
进行强缓存,以提高开发期间的页面重新加载性能。一旦缓存,这些请求将永远不会再次命中开发服务器。如果安装了不同的版本(如包管理器锁定文件中反映的那样),则通过附加的版本查询自动使它们失效。如果你想通过进行本地编辑来调试依赖项,可以
- 通过浏览器的开发者工具的“网络”选项卡临时禁用缓存;
- 使用
--force
标志重新启动 Vite 开发服务器以重新构建依赖项; - 重新加载页面。