跳至内容

依赖预打包

当你第一次运行 vite 时,Vite 会在本地加载你的网站之前预打包你的项目依赖。默认情况下,它会自动且透明地完成。

原因

这是 Vite 执行我们称之为“依赖预打包”的操作。此过程有两个目的

  1. CommonJS 和 UMD 兼容性:在开发过程中,Vite 的开发服务器将所有代码作为原生 ESM 提供。因此,Vite 必须首先将作为 CommonJS 或 UMD 提供的依赖项转换为 ESM。

    在转换 CommonJS 依赖项时,Vite 会执行智能导入分析,以便即使导出是动态分配的(例如 React),对 CommonJS 模块的命名导入也能按预期工作。

    js
    // works as expected
    import React, { useState } from 'react'
  2. 性能: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.includebuild.commonjsOptions.include 中你的配置。

js
export default 
defineConfig
({
optimizeDeps
: {
include
: ['linked-dep'],
},
build
: {
commonjsOptions
: {
include
: [/linked-dep/, /node_modules/],
}, }, })

在对链接依赖项进行更改时,使用 --force 命令行选项重新启动开发服务器,使更改生效。

自定义行为

默认的依赖发现启发式方法可能并不总是理想的。在你想明确地包含/排除依赖项列表的情况下,请使用 optimizeDeps 配置选项.

optimizeDeps.includeoptimizeDeps.exclude 的一个典型用例是,当你的导入不是直接在源代码中发现的。例如,导入可能是由于插件转换而创建的。这意味着 Vite 无法在初始扫描中发现导入 - 它只能在浏览器请求文件并进行转换后才能发现它。这会导致服务器在服务器启动后立即重新打包。

includeexclude 都可以用来处理这个问题。如果依赖项很大(具有许多内部模块)或为 CommonJS,那么你应该包含它;如果依赖项很小且已经是有效的 ESM,则可以排除它,让浏览器直接加载它。

你还可以使用 optimizeDeps.esbuildOptions 选项 进一步自定义 esbuild。例如,添加一个 esbuild 插件来处理依赖项中的特殊文件,或更改 构建 target.

缓存

文件系统缓存

Vite 将预打包的依赖项缓存到 node_modules/.vite 中。它根据以下几个来源确定是否需要重新运行预打包步骤

  • 包管理器锁定文件内容,例如 package-lock.jsonyarn.lockpnpm-lock.yamlbun.lockb
  • 补丁文件夹修改时间。
  • 你的 vite.config.js 中的相关字段(如果有)。
  • NODE_ENV 值。

只有当上述内容之一发生更改时,才需要重新运行预打包步骤。

如果出于某种原因,你想要强制 Vite 重新打包依赖项,你可以使用 --force 命令行选项启动开发服务器,或者手动删除 node_modules/.vite 缓存目录。

浏览器缓存

解析的依赖项请求使用 HTTP 标头 max-age=31536000,immutable 强烈缓存,以提高开发期间的页面重新加载性能。一旦缓存,这些请求将永远不会再次命中开发服务器。如果安装了不同的版本(如你的包管理器锁定文件中反映的那样),它们会通过附加的版本查询自动失效。如果你想通过进行本地编辑来调试你的依赖项,你可以

  1. 通过浏览器开发者工具的“网络”选项卡暂时禁用缓存;
  2. 使用 --force 标志重新启动 Vite 开发服务器以重新打包依赖项;
  3. 重新加载页面。