通过vite中rollup打包,如何对lodash做按需打包?

通过vite中rollup打包,如何对lodash做按需打包?

import {throttle} from 'lodash'
import throttle from 'lodash/throttle'

这两种写法在build时 第一种dist体积比第二种要大。都说是第一种写法是将整个lodash打包进了dist。我这里有一个疑问,rollup在build时不是会对代码做按需打包吗? rollup的树摇不会起作用吗? 假设整个项目只使用了一个throttle函数,也会将整个lodash打包到dist吗?

虽然lodash是 cjs规范的,我理解在编译是应该会被转换成esm。
node_modules/lodash包里每个函数都是单独文件,在node_modules/lodash/index.js里仅仅对这些文件做了集合 按理说这种分散的方式会被按需打包啊。
我在网上查了说rollup的树摇操作只能识别esm模块?

阅读 1.8k
avatarAI BotBETA

在Vite中使用Rollup进行打包时,确实可以优化打包体积,但这依赖于几个关键因素,包括模块的类型(ESM vs CJS)、导入语句的写法以及Rollup插件的配置。对于lodash这样的库,尽管它内部是模块化的(每个函数作为单独的文件存在),但如果你直接从lodash包的主入口文件导入(即使用import {throttle} from 'lodash'),Rollup可能无法有效地进行树摇(Tree Shaking),因为这通常依赖于ES模块(ESM)的静态导入分析。

解释

  1. ESM vs CJS:

    • ESM(ECMAScript Modules)支持静态分析,这意味着Rollup可以在打包前确定哪些代码是实际需要的,哪些可以被排除。
    • CJS(CommonJS)模块则不支持这种静态分析,因为CommonJS的require调用是动态的,Rollup难以在编译时确定具体需要哪些部分。
  2. lodash的导入方式:

    • 当你使用import {throttle} from 'lodash'时,你实际上是从lodash的CJS主入口文件导入,这个文件可能包含了lodash的所有功能或至少是一个包含大量功能的集合。Rollup在这种情况下可能无法精确地进行树摇,因为它依赖于lodash内部模块化的结构来识别哪些部分被实际使用。
    • 使用import throttle from 'lodash/throttle'时,你直接从lodash的ESM构建中导入单独的throttle模块,这样Rollup可以更容易地识别并只包含这个特定的模块。
  3. Rollup的配置:

    • 确保你的Rollup配置或Vite配置启用了对ESM的支持,并且配置了适当的插件来处理node_modules中的依赖。

解决方案

  • 使用直接导入: 尽可能使用import throttle from 'lodash/throttle'这样的直接导入方式,以确保只包含所需的lodash函数。
  • 配置Rollup插件: 如果你需要处理一些特殊情况或想要进一步优化打包体积,可以考虑使用Rollup插件,如@rollup/plugin-commonjs来转换CommonJS模块为ESM,但这通常不是必要的,因为lodash已经提供了ESM版本。
  • 检查Vite配置: 确保Vite配置正确,以支持ESM和树摇。

结论

虽然lodash的CJS主入口文件试图通过内部模块化的方式支持树摇,但直接从该入口文件导入时,Rollup可能无法有效地识别并排除未使用的代码。最佳实践是直接从lodash的ESM入口导入所需的函数,以确保只包含必要的代码。

2 个回答

能否做 tree-shaking 要看lodash 的导出方式,

// index.js

export { default as throttle } from "./throttle.js"
// 如果是这样的导出,那么会启动tree-shaking , 只打包 throttle 
// index.js
export function throttle (){

}
// 如果是这样的导出,那么整个index.js 都会被打包

loadash 有 esm 版本的 lodash-es

lodash 的cjs版本使用的是 module.exports = { throttle }
这种方式不会触发 tree-shaking , 因为 esm 才是官方支持 cjs 是社区规范

你找的资料都是对的,可以考虑换 lodash-es

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏