npm package 打包针对不同运行环境要做什么处理?

新手上路,请多包涵

问题描述

我有一个 package 就叫它 - MyPKG 引用了 lodash.debounce, MyPKG 的运行环境为: [浏览器, nodejs, es-module]

MyPKG 使用 rollup 打包进行了 tree shaking, 只将 lodash.debounce 打包进去了, 输出一个 umd 模块, 所有环境均使用这个打包结果 (言下之意就是 package.json 中, main,browser,module,unpkg 均指向同一个文件)

但是我认为这样做仍然存在问题:
1.如果用户的项目也使用了 lodash, 那么用户的构建产物, 可能包含两份 lodash.debounce
2.如果用户的项目也使用了 lodash, 当用户的 lodash 和 MyPKG 的 lodash 版本不一致的时候, 用户将会安装两个版本的 lodash.

基于如上的问题, MyPKG 将会是一个不受欢迎的 package.

我的期望结果

大致了解了一下 peerDependence 字段

1.浏览器环境: 输出一份 amd 模块, 包含 lodash.debounce
2.nodejs 环境输出一份 commonjs 模块, 包含 lodash.debounce
3.jsnext:main 输出一份 es6 模块, 是否包含 lodash.debounce 要根据用户本地环境决定

我的初步方案

针对不同运行环境进行差异化构建, 可能要使用三份 rollup 配置吧?

我希望了解的答案

1.针对我的问题, 应该不是个例, 有相关文章是讲解这个问题的吗?
2.很多包都有这样的需求, 有没有最佳实践可以推荐一下, 或者说科普一下?

阅读 3.3k
1 个回答

首先,要看你引的包是否显式地被引用。如果被显式引用并且最终运行时作为依赖,应放到dependencies中。

其次,不相关的包不应被并入你的代码。而且有时还会有许可证侵权问题。

如果你一定要捆绑依赖包,可以使用bundleDependencies,一般仅在你需要合并多个自己开发的包的时候。如开发一个预设preset

rollup中,可以将依赖设置为external。被设为外部模块的引用将不会被编译入最终代码。

理论上,只需要output的部分配置针对各个环境单独设定,其他的都可以共用。

一般而言,针对浏览器构建esmumd格式的目标。因为这两种格式都能单独运行于浏览器环境中,而无需其他加载器,同时也可以被现代编译工具正确识别。额外地,常见地可以构建commonjs格式的目标,可以被使用node.js的编译工具很好地读取。

针对node.js环境,应首先确保构建commonjs格式的目标,它是node.js的默认支持格式。额外地,可以构建esm格式的目标,它也能被较新的node.js支持,但需要注意在package.json中将module指向它才可以被正确读取。

当用户安装你发布的包时,会安装dependencies中的包。此时,如果用户指定了和你的包中引用相同的包,且用户所安装的包符合你包中引用的依赖的版本条件,则只会安装一次(视npm版本)。如果不符合版本条件,则会额外安装符合版本条件的较新的包。所以,对于你的包而言,所引用的依赖一定能符合你指定的版本条件。

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