react-virtuoso icon indicating copy to clipboard operation
react-virtuoso copied to clipboard

[BUG] Tree shaking doesn't work (Table and Grid components are still included despite not importing them)

Open michael42 opened this issue 2 years ago • 1 comments

Describe the bug When importing react-virtuoso, it seems that none of the popular bundlers are able to omit unneeded parts of react-virtuoso. That makes bundle sizes larger than necessary (~24 KiB before minification/compression).

Reproduction See https://github.com/michael42/react-virtuoso/tree/tree-shaking-test, I added rollup the repo and made a few test bundles, importing different things.

To Reproduce Steps to reproduce the behavior:

  1. Import only some components of react-virtuoso in a project (e.g. here)
  2. Bundle the result using parcel 2 or rollup (not sure about webpack)
  3. Look at the produced bundle, the unused components are still included, e.g. for the linked example the output sizes are withing 15 bytes of each other (50.5 KiB)

Expected behavior I expected only the List-Component to be included when I don't use the Grid or Table.

Screenshots From a parcel report when using just import {Virtuoso} from "react-virtuoso": image

Desktop (please complete the following information):

  • OS: Linux
  • Browser: n/a

Additional context I tried to look into why exactly tree shaking fails, but so far I had no success using export { Table as TableVirtuoso } from './Table' in components.tsx and no success manually placing /* #__PURE__ */ annotations all over the exports and consts.

It's probably possible to package the library like this (but I don't think microbundle supports that directly):

  • index.js: simply re-exports the other files
  • List.js
  • Grid.js
  • Table.js
  • common.js: includes the common code exported by the bundles above

A rollup-config like this produces such output:

export default {
    input: {
        index: 'src/index.tsx',
        List: 'src/List.tsx',
        Grid: 'src/Grid.tsx',
        Table: 'src/Table.tsx'
    },
    output: [{dir: 'build', format: 'esm'}],
    plugins: [typescript()]
}

What do you think, is this worth exploring/optimizing?

michael42 avatar Feb 06 '22 17:02 michael42

I think it might be nice to do so, although the gains are not going to be so enormous, as the list (powering the flat, grouped, and table components) is the biggest piece of code. I would love to accept a PR for that.

petyosi avatar Feb 06 '22 19:02 petyosi

:tada: This issue has been resolved in version 4.0.0 :tada:

The release is available on:

Your semantic-release bot :package::rocket:

github-actions[bot] avatar Jan 01 '23 09:01 github-actions[bot]

@michael42 I had to throw a bunch of PURE comments here and there, but based on what I tested, tree shaking works with esbuild, at least. Bundlephobia does not recognize that, though.

petyosi avatar Jan 01 '23 10:01 petyosi

Awesome, thanks, that seems to work great. I tried adding some /** @__PURE__ */-comments, too, but didn't get good results with parcel and gave up on that approach.

michael42 avatar Jan 08 '23 15:01 michael42