依赖预构建是:
来自vite官网的解释——
在转换 CommonJS 依赖项时,Vite 会进行智能导入分析,这样即使模块的导出是动态分配的(例如 React),具名导入(named imports)也能正常工作:
依赖预构建是针对node_modules里的依赖进行的预处理,另外,依赖预构建是针对本地运行的时候,那么本地运行是esbuild进行的编译,最终浏览器加载的esModule模块规范的代码。
依赖预处理完成的工作:
1. 模块规范的转换:例如,有的第三方依赖是commonJS规范,那么需要将其转换成esModule规范的代码。同时存放在node_modules/.vite/deps目录下。同时,也会处理依赖的依赖,并将依赖的所有依赖都统一集成。
2. 解决依赖请求过多的问题:例如,lodash库,它本身也会依赖其他库,比如会在lodash-es的package.json文件中的peerDenpendency中指定依赖,依赖也会存在其他依赖。如果依赖过多,那么,会造成浏览器加载请求次数过多,对性能造成影响。
例如,在vite.config.js文件中添加如下配置:
optimizeDeps: {
include: [], // 默认情况下,不在 node_modules 中的,链接的包不会被预构建。使用此选项可强制预构建链接的包。
exclude: ['lodash-es'] //在预构建中强制排除的依赖项。
},
本地运行:npm run dev
可以看出浏览器发送了大量的请求,请求发出者是lodash
依赖预处理缓存文件更新:
预构建的依赖项缓存到 node_modules/.vite,
它会基于以下几个来源来决定是否需要重新运行预构建步骤:
来自官网——
- 包管理器的锁文件内容,例如
package-lock.json
,yarn.lock
,pnpm-lock.yaml
,或者bun.lockb
;- 补丁文件夹的修改时间;
vite.config.js
中的相关字段;NODE_ENV
的值。
删除预处理缓存文件:
1. 手动找到node_modules/.vite/deps目录,手动删除内容
2.配置package.json的script的时候,vite 命令添加--force,本地服务器启动的时候会强制重新进行依赖预处理
解决本地强缓存:
来自vite官网:
- 通过浏览器开发工具的 Network 选项卡暂时禁用缓存;
- 重启 Vite 开发服务器指定
--force
选项,来重新构建依赖项;- 重新载入页面。
Monorepo 和链接依赖:
(官方的翻译看不太懂,解释如下:)
Monorepo(单仓库):这是一种项目管理策略,即把多个相关的项目(比如微服务、库或者应用的不同部分)放在同一个版本控制系统仓库中管理,而不是为每个项目创建单独的仓库。这样做的好处包括更方便地进行跨项目代码共享、统一管理依赖和简化版本控制等。
链接依赖(Linked Dependencies):在单仓库环境下,当你正在开发的包A需要依赖另一个也在该仓库中的包B时,可以通过“链接”方式让包A直接使用包B的源代码,而不是通过npm安装包B到
node_modules
目录下。这样做可以加快开发速度,因为修改包B后,包A能立即感知并使用到最新代码,无需重新安装。Vite如何处理
自动侦测与源码处理:Vite能够自动检测到那些没有从标准的
node_modules
目录解析的依赖。对于这类链接依赖,Vite不会将它们当作外部依赖来打包,而是直接将它们作为源码处理。这意味着Vite会直接读取和编译这些依赖的源代码,而非使用编译后的产物。ESM格式要求:为了能够正确处理这些链接依赖,被链接的包需要导出为ES模块(ESM, EcmaScript Modules)格式。ESM是现代JavaScript模块系统,支持动态导入、顶级await等特性,是未来Web开发的标准。
配置优化:如果被链接的依赖不是ESM格式,可以通过Vite的配置来解决这一问题。你需要在
vite.config.js
文件中,将这个依赖添加到optimizeDeps.include
中,以及build.commonjsOptions.include
中,以便Vite正确处理这些非ESM格式的依赖。变更检测与强制重启:由于Vite在开发模式下提供了热更新功能,但对链接依赖的变动可能无法立即感知。因此,当对链接依赖做出修改后,需要使用
--force
选项重启开发服务器,以确保所有更改生效。这强迫Vite重新分析依赖关系并应用最新改动。
总结:
1. 微前端,或者多个应用放在同一个代码库中。彼此之间会相互引用依赖,这些依赖没必要再通过npm方式安装。因为文件会被频繁修改,如果采用 npm方式,那么需要更新安装。
2. vite对于这种依赖,会把它看成是源码,既然是源码就要遵从esModule模块规范。如果不是esModule,那么就需要通过optimizeDeps.include和build.commonJsOptions.include进行依赖优化。第一个配置选项是为了研发阶段,第二个是为了生产编译输出阶段。
依赖启发式算法:
Vite使用一套默认的算法(称为依赖启发式算法)来自动发现和预构建(pre-bundle)项目中的依赖,以加速开发环境的启动和运行时性能。然而,这套默认算法可能不是在所有情况下都能完美匹配项目需求,特别是当项目结构复杂或使用了特殊构建工具和插件时。
optimizeDeps.include
与optimizeDeps.exclude
的应用场景
-
include
: 应用于大型依赖或CommonJS模块。大型或内部模块众多的依赖通过预构建可以显著提升加载速度,而CommonJS模块通常需要转换为ES模块格式以便于Vite更好地优化和处理。 -
exclude
: 适用于小型且已经是有效ES模块格式的依赖。这样的依赖可以直接让浏览器加载,减少预构建步骤,进一步优化构建时间和资源利用。
总结:
1. optimizeDeps是针对本地研发环境的依赖进行优化
2. optimizeDeps.include能够解决的问题:
a. vite的
依赖启发式算法无法发现的依赖(例如,源码中没有import,但是babel转换成esModule后又有了import),可以添加到include中
b. 如果依赖是commonJS,且非npm安装的,可以通过include进行转码