Skip to content
On this page

依赖预构建

Vite是一个提倡no-boundle的构建工具,相比于Webpack,可以做到开发时模块按需编译,这里的模块分为两部分

  • 一部分是自己写的业务代码

  • 一部分是依赖的第三方库,即node_modules中的第三方库的代码

TIP

  • Vite中的no-bundle只是针对于自己写的业务代码,对于依赖的第三方库Vite选择使用esbuild进行bundle(打包)

  • 依赖预构建仅作用于开发环境,使用esbuild将依赖转换为ES Module规范,在生产环境中,使用@rollup/plugin-commonjs代替

为什么需要依赖预构建

  • 统一项目依赖库的导入/导出规范:当项目中有依赖库是非ES Module的语法,例如CommonJSUMD语法时,Vite会调用esbuild将其转换为ES Module规范的代码

react这个库就没有ES版本的产物,其仍旧是commonjs语法

  • 方便路径重写,统一项目中第三方模块的导入路径:在依赖预构建时,对导入的第三方包进行统一处理,处理后的结果放到当前项目的node_modules/.vite/deps目录下,并且在引入该模块的地方进行路径重写,这样就统一所有资源的引入路径
js
// 路径重写前
import _ from 'lodash-es';
// 路径重写之后
import _ from "/node_modules/.vite/deps/lodash-es.js?v=a2b41ab7"
  • 解决网络多包传输问题,如果没有依赖预构建,当一个模块中import的模块/方法很多,而依赖的模块中又import了其他模块/方法时,每个import都会创建一个http请求,导致页面加载十分缓慢,例如下面的lodash-es库,而使用依赖预构建后,会将这个库的代码打包成一个文件,这样就减少了很多请求,页面加载也会快很多

lodash-es库,当关闭依赖预构建功能后,由于其是ES Module规范,会引发大量http请求,造成不必要的网络开销

开启依赖预构建后,Vite将内部多个模块的ESM依赖关系转换为单个模块,提高后续页面加载性能

依赖预构建相关配置

官网地址戳这里查看

optimizeDeps.entries

  • Type: string | string[]

默认情况下,Vite会默认抓取项目中所有的.html文件,将HTML文件作为应用入口,然后根据入口文件扫描出项目中用到的第三方依赖,最后对这些依赖逐个进行编译

如果不满足需求,可以通过自定义entries来自定义入口文件

例如vite.config.js:

javascript
{
  optimizeDeps: {
    // 为一个字符串数组
    entries: ["./src/app.tsx"];
  }
}

entries也支持glob语法

例如

javascript
// 将所有的 .ts 文件作为扫描入口 
entries: ["**/*.ts"];

optimizeDeps.exclude

  • Type: string[]

exclude用于设置某些依赖不进行依赖预构建

在排除某个依赖时,要注意该依赖所依赖的其他包是否有ES Module产物,如果其中有的包没有ES Module产物将会报错,遇到这种情况,可以搭配include使用,将依赖的其他包中没有ES Module的包进行依赖预构建

vite.config.js

javascript
{
  optimizeDeps: {
    include: [
      // 间接依赖的声明语法,通过`>`分开, 如`a > b`表示 a 中依赖的 b
      "a > b",
    ];
} }

optimizeDeps.include

  • Type: string[]

默认情况下,不在node_modules内的链接包不会进行依赖预构建,使用此选项可以指定将某些包进行依赖预构建

javascript
optimizeDeps: {
    // 配置为一个字符串数组,将lodash-es、vue和src/components下的所有.vue文件强制进行预构建
    include: ["lodash-es", "vue", "src/components/*.vue"];
}

optimizeDeps.esbuildOptions

依赖(dep)扫描优化期间传递给esbuild的选项

TIP

  • 某些选项被省略,因为更改它们将与Vite的依赖优化不兼容

  • plugins会与Vite的依赖插件合并

optimizeDeps.force

  • Type: boolean

设置为true以强制依赖项预捆绑,忽略先前缓存的优化依赖项。

optimizeDeps.disabled

该选项目前还是实验性的阶段

  • Type: boolean | 'build' | 'dev',默认值为build

该选项表示禁用依赖预构建`的情况

  • 设置为true表示在生产环境开发环境禁用依赖预构建

  • 设置为builddev,仅在其中一种模式下禁用依赖预构建,默认情况下,仅在开发中启用依赖预构建

缓存

文件系统缓存

Vite将依赖预构建的结果缓存在node_modules/.vite中。它根据以下几个来源确定是否需要重新进行预构建

  • 包管理器的lock文件,如package-lock.jsonyarn.lock, pnpm-lock.yamlbun.lockb

  • 补丁文件夹(一般是patch-package)修改的时间

  • vite.config.js中的预构建的相关配置

  • 环境变量NODE_ENV的值

以上的选项中,有一个改变就会重新进行预构建

如果以上选项均为改变,但是想重新进行预构建,可以使用--force选项或者手动删除node_modules/.vite缓存目录

浏览器缓存

当请求依赖预构建后的资源时,ViteDev Server会在响应头中添加Cache-Control: max-age=31536000,immutable来设置强缓存,缓存过期时间被设置为一年,表示缓存过期前浏览器对预构建产物的请求不会再经过Vite Dev Server,会直接用缓存的内容

![](/image/Vite/pre-built/3.png

如果想调试第三方库的源码,让浏览器加载添加debug调试后的源代码,可以通过以下步骤

  • 修改node_module中的第三方库的源代码,中止Vite Dev Server重新启动,并添加--force选项

例如

vite.config.js

javascript
import { get } from 'lodash-es'

const data = {
    classes: {
        one: {
            name: '小明'
        }
    }
}
console.log(get(data, 'classes.one.name'), '============')

修改node_modules/lodash-es/_baseGet.js如下:

然后重启服务

shell
pnpm dev --host --force

可以看到命令行中会提示重新进行依赖预构建

然后到浏览器中查看,刚才添加的debug信息已经打印

其他