您如何通过webpack使图书馆真正可摇树?

时间:2018-12-06 13:19:30

标签: reactjs webpack tree-shaking

我有一个包含多个react组件的库,并且我想使该库可摇树,以便在导入

之类的组件时
import { Checkbox } from 'my-react-components'

我不导入整个捆绑包。

我的index.js看起来像这样

export { default as Button } from './components/Button'
export { default as Checkbox } from './components/Checkbox'
export { default as FlexView } from './components/FlexView'
export { default as Radio } from './components/Radio'
export { default as Select } from './components/Select'
export { default as TextInput } from './components/TextInput'
export { default as Toggle } from './components/Toggle'

然后我使用webpack捆绑

module.exports = {
  mode: 'production',
  entry: './src/index.ts',
  output: {
    path: path.resolve('./lib'),
    filename: 'react-components.js',
    libraryTarget: 'commonjs2',
  },

  // loaders and stuff...
  // terser-webpack-plugin...

  externals: {
    // don't include react in the bundle
    react: {
      root: 'React',
      commonjs2: 'react',
      commonjs: 'react',
      amd: 'react',
    },
  },
  optimization: {
    splitChunks: false,
    sideEffects: false,
  },
}

当然,在我的babel配置中,

['@babel/preset-env', {
  modules: false,
}]

通过这种设置,当我仅导入一个组件,并且包含整个捆绑包时(导入时我也在使用webpack)。我该如何预防?

4 个答案:

答案 0 :(得分:2)

截至2020年2月,Webpack无法实现。

因为树的摇动机制在很大程度上依赖于ES6 import/export,并且Webpack当前不支持output.libraryTarget中的ES2015模块格式。

作为替代方案,您可以将您的图书馆与其他捆绑软件(如Rollup(确实支持图书馆的ES6模块))捆绑在一起。

您可以在此处跟踪此功能:https://github.com/webpack/webpack/issues/2933

更新: 尽管存在一些变通的解决方法:https://stackoverflow.com/a/60010871/921193

答案 1 :(得分:1)

我相信您还需要module上的package.json属性

{
   ...
   "main": "lib/index.js",
   "module": "lib/index.esm.js",
   ...
}

答案 2 :(得分:1)

我能够通过直接从库的lib文件夹中导入文件来工作,而不仅仅是自己命名库。

以我为例,我从Reactstrap库中导入了一些组件,如下所示:

import Button from 'reactstrap/lib/Button';
import UncontrolledPopover from 'reactstrap/lib/UncontrolledPopover';
import PopoverHeader from 'reactstrap/lib/PopoverHeader';
import PopoverBody from 'reactstrap/lib/PopoverBody';

答案 3 :(得分:0)

有效的babel plugin可根据您指定的规则帮助您转换导入。

[
   'transform-imports', // or 'babel-plugin-transform-imports'
   {
     'react-router': {
       transform: 'react-router-dom/${member}',
       preventFullImport: true
     },
     reactstrap: {
       transform: 'reactstrap/lib/${member}',
       preventFullImport: true
     }
   }
]

注意: 如果您想确保导入到该路径的文件可摇晃,则preventFullImport很有用。


这只是帮助您有效地摇晃未使用的导入的另一种实现方式。但是从长远来看,直接导入每个文件是最佳做法。

import Button from 'reactstrap/lib/Button';
import UncontrolledPopover from 'reactstrap/lib/UncontrolledPopover';