知海

依赖预构建

vite-main使用指南

依赖预构建

当你首次运行 vite 时,Vite 会在本地加载站点之前预构建项目依赖。这一过程默认自动且透明地完成。

为什么需要预构建

这就是 Vite 所执行的“依赖预构建”过程。该过程有两个目的:

  1. CommonJS 和 UMD 兼容性: 在开发期间,Vite 将所有代码作为原生 ESM 提供。因此,Vite 必须先将以 CommonJS 或 UMD 形式发布的依赖转换为 ESM。

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

    js 复制代码
    // 按预期工作
    import React, { useState } from 'react'
  2. 性能: Vite 会将包含许多内部模块的 ESM 依赖转换为单个模块,以提高后续页面加载性能。

    有些包将其 ES 模块构建产物作为许多相互导入的独立文件发布。例如,lodash-es 有超过 600 个内部模块!当我们执行 import { debounce } from 'lodash-es' 时,浏览器会同时发起 600+ 个 HTTP 请求!尽管服务器处理这些请求没有问题,但大量的请求会在浏览器端造成网络拥塞,导致页面加载明显变慢。

    通过将 lodash-es 预构建为单个模块,现在我们只需要一个 HTTP 请求!

::: tip 注意
依赖预构建仅适用于开发模式。
:::

自动依赖发现

如果未找到现有缓存,Vite 会抓取你的源代码并自动发现依赖导入(即需要从 node_modules 解析的“裸导入”),并将这些发现的导入作为预构建的入口点。预构建使用 Rolldown 执行,因此通常非常快速。

服务器启动后,如果遇到了尚未缓存的新的依赖导入,Vite 将重新运行依赖打包过程,并在需要时重新加载页面。

Monorepo 和链接依赖

在 monorepo 设置中,依赖可能是来自同一仓库的链接包。Vite 会自动检测未从 node_modules 解析的依赖,并将链接的依赖视为源代码。它不会尝试打包链接的依赖,而是分析链接依赖的依赖列表。

但这要求链接的依赖以 ESM 形式导出。如果不是,你可以将依赖添加到配置中的 optimizeDeps.include

js twoslash [vite.config.js] 复制代码
import { defineConfig } from 'vite'
// ---cut---
export default defineConfig({
  optimizeDeps: {
    include: ['linked-dep'],
  },
})

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

自定义行为

默认的依赖发现启发式策略并不总是理想的。如果你希望显式地从列表中包含或排除依赖,请使用 optimizeDeps 配置选项

optimizeDeps.includeoptimizeDeps.exclude 的一个典型使用场景是:当存在无法在源代码中直接发现的导入时。例如,该导入可能是由插件转换的结果。这意味着 Vite 无法在初始扫描时发现该导入——它只能在文件被浏览器请求并转换后才能发现。这会导致服务器在启动后立即重新打包。

includeexclude 都可以用来处理这种情况。如果依赖很大(包含许多内部模块)或是 CommonJS,那么你应该将其包含(include);如果依赖很小且已是有效的 ESM,你可以将其排除(exclude),让浏览器直接加载它。

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

缓存

文件系统缓存

Vite 将预构建的依赖缓存在 node_modules/.vite 中。它根据以下几个来源判断是否需要重新运行预构建步骤:

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

只有当以上任一条件发生变化时,才需要重新运行预构建步骤。

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

浏览器缓存

解析后的依赖请求会通过 HTTP 头 max-age=31536000,immutable 进行强缓存,以提高开发时的页面重新加载性能。一旦被缓存,这些请求将不再访问开发服务器。当安装了不同版本(反映在你的包管理器锁文件中)时,它们会通过附加的版本查询参数自动失效。如果你想通过本地修改来调试依赖,可以:

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

帮助我们改进文档

发现翻译问题或内容错误?请告诉我们。