Tree shaking not working for the react component library using named imports

708 views Asked by At

Our company projects count is growing, so we decided to move our ui kit to a separate private npm package. For building kit before publishing we decided to use rollup. The file structure for ui kit is quite standard we've:

src
       - Components
         - Alert
         - Button
         - Heading
         - ...
       HOC, static...

       - index.js

Root index.js file is used only for reexporting all components.

export {default as Alert} from './Components/Alert';
export {default as Button} from './Components/Button';
...

Our main goal is to be able to get components from our kit using named imports.

import {Alert, Button} from '@company/ui-kit';

Properly working tree shaking is also important, because some of our projects are using only 2/31 components from the kit, so we want to see in final build only components what has been used and this is the main challenge. We tried many options of rollup config with single output file or chunks and realized, that tree shaking only works with chunks and what's more interesting it works only with importing chunk directly, not named import from the index.js.

import Alert from '@company/ui-kit/Alert'; // tree shaking works, only Alert get into build
import {Alert} from '@company/ui-kit'; // tree shaking not working, all kit components are got into the build

Could somebody explain me why this is happening? And is there any way to use named imports with properly working tree shaking. What is also very curious, that we tried to test tree shaking with named imports in some popular libraries like material ui and there it's not working too. Tree shaking works only with direct import from chunk.

Also need to mention that we tested tree shaking only in projects created with create-react-app. I don't really think the problem could be inside create-react-app bundler config, but maybe it will help to figure out this.

For the full picture also attaching our rollup config:

import multiInput from 'rollup-plugin-multi-input';
import babel from 'rollup-plugin-babel';
import commonjs from 'rollup-plugin-commonjs';
import external from 'rollup-plugin-peer-deps-external';
import resolve from 'rollup-plugin-node-resolve';
import copy from 'rollup-plugin-copy'
import postcss from 'rollup-plugin-postcss';
import postcssUrl from 'postcss-url';
import asset from "rollup-plugin-smart-asset";

export default {
    input: ['src/index.js', 'src/Components/**/*.js'],
    output: [
        {
            dir: './',
            format: 'cjs',
            sourcemap: true,
            exports: 'auto',
            chunkFileNames: '__chunks/[name]_[hash].js'
        }
    ],
    plugins: [
        multiInput({relative: 'src/'}),
        external(),
        postcss({
            modules: false,
            extract: true,
            minimize: true,
            sourceMap: true,
            plugins: [postcssUrl({url: 'inline', maxSize: 1000})],
        }),
        copy({targets: [{src: 'src/static/icons/fonts/*', dest: 'fonts'}]}),
        babel({exclude: 'node_modules/**'}),
        asset({url: 'copy', keepImport: true, useHash: false, keepName: true, assetsPath: 'assets/'}),
        resolve(),
        commonjs({include: 'node_modules/**'})
    ]
};

Thanks in advance for your replies!

0

There are 0 answers