vite中的依赖预构建 到底是什么 做了什么

1. 什么是依赖预构建?

在现代前端开发中,项目中通常会依赖大量第三方库(如 lodashaxiosreact 等)。这些库通常是用 CommonJS 或其他格式编写的,而 Vite 的开发服务器是基于 ESM(原生 ES 模块)运行的。

为了让这些第三方库能够高效地被浏览器加载,Vite 会在开发服务器启动之前,对这些依赖进行一次预构建(Pre-Bundling),将它们转换为浏览器友好的 ESM 格式,并进行优化。

2. 为什么需要依赖预构建?

问题一:CommonJS 和 UMD 格式不兼容 ESM

  • 大多数 NPM 上的库使用 CommonJS 或 UMD 格式,这些格式不能直接被浏览器识别。
  • 如果不进行预构建,Vite 在运行时需要动态转换格式,性能会大打折扣。

问题二:模块的深层依赖解析慢

  • 许多第三方库会依赖其他库(深层依赖链),浏览器需要逐个解析这些依赖,可能会导致请求过多和加载缓慢。
  • 例如,lodash-es 中有许多子模块,如果不预构建,浏览器需要逐个请求这些模块,增加了网络开销。

问题三:重复解析

  • 如果多个文件引用了同一个依赖,浏览器会多次解析,造成性能浪费。

解决方案:Vite 的依赖预构建

  • Vite 使用 esbuild 将第三方依赖预先打包成单个 ESM 文件,避免了上述问题。
  • 预构建后的依赖会被缓存,只有在依赖发生变化时才会重新构建。

3. Vite 的依赖预构建流程

第一步:识别依赖

  • Vite 会扫描项目的 import 语句,识别出第三方依赖(通常是从 node_modules 中引入的库)。

  • 例如:

    javascript 复制代码
    import React from 'react';
    import _ from 'lodash';

    Vite 会将 reactlodash 识别为需要预构建的依赖。

第二步:使用 esbuild 进行预构建

  • Vite 使用 esbuild 对这些依赖进行一次性打包,将它们转换为 ESM 格式。
  • 例如,react 的 CommonJS 文件会被转换为浏览器可用的 ESM 文件。

第三步:缓存预构建结果

  • 预构建的依赖会被缓存到 node_modules/.vite 目录中。
  • 如果依赖没有发生变化,Vite 会直接使用缓存,而不会重复构建。

4. 依赖预构建的优化点

1. 合并模块

  • Vite 会将一个依赖及其子依赖合并为一个文件,减少浏览器的网络请求数量。
  • 例如,lodash-es 中的多个子模块会被合并为一个文件。

2. 提升解析速度

  • 通过 esbuild 的超快解析能力(用 Go 编写,比 JavaScript 实现快 10-100 倍),依赖预构建速度非常快。

3. 支持 Tree Shaking

  • 对于支持 Tree Shaking 的依赖(如 lodash-es),Vite 的预构建会保留模块的按需加载能力,避免打包无用代码。

4. 缓存机制

  • 预构建结果会被缓存到本地(node_modules/.vite),只有当依赖版本或配置发生变化时才会重新预构建,避免重复工作。

5. 配置依赖预构建

Vite 提供了一些配置选项来控制依赖预构建的行为。

自动预构建

  • 默认情况下,Vite 会自动识别项目中的第三方依赖并进行预构建。
  • 如果需要手动指定依赖,可以通过 optimizeDeps 配置。

常用配置选项

1. 强制预构建的依赖

  • 如果某些依赖没有被自动预构建,可以手动指定:

    arduino 复制代码
    export default {
      optimizeDeps: {
        include: ['lodash', 'axios']
      }
    }

2. 排除某些依赖

  • 如果某些依赖不需要预构建,可以排除:

    arduino 复制代码
    export default {
      optimizeDeps: {
        exclude: ['some-large-library']
      }
    }

3. 禁用预构建

  • 在特殊情况下,你可以禁用依赖预构建:

    arduino 复制代码
    export default {
      optimizeDeps: {
        disabled: true
      }
    }

6. 依赖预构建的效果

开发服务器启动速度提升

  • 通过预构建,Vite 避免了在启动时动态解析第三方依赖,大幅减少了开发服务器的启动时间。
  • 对于依赖复杂的大型项目,启动速度提升尤为显著。

减少浏览器请求

  • 预构建会将深层依赖合并为一个文件,减少浏览器的网络请求数量。

提升模块加载性能

  • 预构建后的依赖是 ESM 格式,浏览器可以直接加载,无需额外的动态转换。

7. 实际案例

假设项目中使用了以下依赖:

javascript 复制代码
import React from 'react';
import ReactDOM from 'react-dom';
import _ from 'lodash-es';
  • 未预构建:

    • 浏览器需要分别加载 reactreact-domlodash-es 的多个模块,加载时间较长。
  • 预构建后:

    • Vite 会将 reactreact-dom 合并为一个 ESM 文件,将 lodash-es 的子模块合并为另一个文件。
    • 浏览器只需加载两个文件,性能显著提升。

8. 总结

Vite 的依赖预构建通过以下方式提升了开发效率:

  • 使用 esbuild 对第三方依赖进行超快的预构建。
  • 将依赖转换为 ESM 格式,优化浏览器的加载性能。
  • 合并深层依赖,减少网络请求。
  • 缓存预构建结果,避免重复工作。

依赖预构建是 Vite 快速启动和高效模块加载的关键机制之一,使其在开发体验上相比 Webpack 等传统工具具有显著优势。

相关推荐
TimelessHaze25 分钟前
拆解字节面试题:async/await 到底是什么?底层实现 + 最佳实践全解析
前端·javascript·trae
执键行天涯1 小时前
从双重检查锁定的设计意图、锁的作用、第一次检查提升性能的原理三个角度,详细拆解单例模式的逻辑
java·前端·github
青青子衿越1 小时前
微信小程序web-view嵌套H5,小程序与H5通信
前端·微信小程序·小程序
OpenTiny社区1 小时前
TinyEngine 2.8版本正式发布:AI能力、区块管理、Docker部署一键强化,迈向智能时代!
前端·vue.js·低代码
qfZYG1 小时前
Trae 编辑器在 Python 环境缺少 Pylance,怎么解决
前端·vue.js·编辑器
bug爱好者1 小时前
Vue3 基于Element Plus 的el-input,封装一个数字输入框组件
前端·javascript
Silence_xl2 小时前
RACSignal实现原理
前端
柯南二号2 小时前
【大前端】实现一个前端埋点SDK,并封装成NPM包
前端·arcgis·npm
dangkei2 小时前
【Wrangler(Cloudflare 的官方 CLI)和 npm/npx 的区别一次讲清】
前端·jvm·npm
乔公子搬砖2 小时前
小程序开发提效:npm支持、Vant Weapp组件库与API Promise化(八)
前端·javascript·微信小程序·js·promise·vagrant·事件绑定