如何输出具有允许选择性导入的对等依赖项的 NPM 包?

How to output NPM packages with peer dependencies that allow for selective imports?

我正在发布一个使用一些对等依赖项的模块:

在我的 package.json 文件中,我声明了 peerDependencies:

...
"peerDependencies": {
  "react": ">=16",
  "react-dom": ">=16",
  "@material-ui/core": ">=4",
  "@material-ui/icons": ">=4"
},
...

在我的 webpack 配置中,我声明了外部变量以及 commonjs2 的输出格式(我完全不确定为什么我会使用 commonjs2 而不是 commonjs):

...
output: {
  filename: 'index.js',
  libraryTarget: 'commonjs2',
  path: path.join(__dirname, output),
},
externals: {
  react: 'react',
  'react-dom': 'react-dom',
  '@material-ui/core': '@material-ui/core',
  '@material-ui/icons': '@material-ui/icons',
},
...

这似乎有效,因为我可以看到输出文件中不包含外部组件。但是,在我的项目中包含此包的输出会导致包大小大得多。

我认为这是因为包的输出将我的 import 语句转换为 require 语句,所以在我使用这个包的项目中,对等依赖项定义为 require 语句无法优化。

换句话说,包的输出不是将 @material-ui/core 库作为构建的一部分,而是将其引用为 require('@material-ui/core')

对吗?

打包对等依赖项的正确方法是什么:

  1. 他们遵守 commonjs 模块格式(这是必要的)吗?
  2. 对等依赖的间接导入仍然可以是选择性的?

我认为(但可能是错误的)目前正在发生的事情是:

// In my project where I consume the package
import { Thing } from '@org/package-name'

// And in @org/package-name` source code, I have
import { Card } from '@material-ui/core'

// Which gets transpiled to (more or less)
require('@material-ui/core').Card

// Which means that when I use "Thing", that I'm loading the whole of @material-ui/core

我也试过用 babel-plugin-transform-imports 配置 babel。但我发现我必须为每次导入配置对等依赖项/外部项(@material-ui/core/Card@material-ui/core/List 等)

我发现可行的解决方案是在 preset-env 的 babel 配置中将 targets.esmodules 设置为 true。

我认为这对我有用的原因是我在单个条目中重新导出模块。 commonjs 格式的命名导出在导入时不容易隔离?

但这只是一个猜测。