I have a library of multiple react components, and I want to make the library tree-shakable so that when I import a component like
import { Checkbox } from 'my-react-components'
I don't import the whole bundle.
My index.js looks like this
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'
And I bundle using 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,
},
}
And in my babel config of course I have
['@babel/preset-env', {
modules: false,
}]
With this setup when I import only one component, and the whole bundle gets included (I am using webpack also when I import it). How do I prevent this?
In webpack, tree shaking works with both ECMAScript modules (ESM) and CommonJS, but it does not work with Asynchronous Module Definition (AMD) or Universal Module Definition (UMD).
It relies on the import and export statements to detect if code modules are exported and imported for use between JavaScript files. In modern JavaScript applications, we use module bundlers (e.g., webpack or Rollup) to automatically remove dead code when bundling multiple JavaScript files into single files.
As of February 2020 it is not possible with Webpack.
Because tree-shaking mechanism heavily relies on ES6 import/export
and Webpack currently doesn't support ES2015 module format in output.libraryTarget
.
As an alternative you can bundle your library with other bundlers like Rollup (which does support ES6 modules for libraries).
You can keep track of this feature here: https://github.com/webpack/webpack/issues/2933
UPDATE: Though there is hacky workaround: https://stackoverflow.com/a/60010871/921193
I believe you also need the module
property on your package.json
{
...
"main": "lib/index.js",
"module": "lib/index.esm.js",
...
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With