Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BREAKING] ES6 tree-shaking by only using named exports and preserving modules #1888

Merged
merged 6 commits into from Aug 24, 2023

Conversation

bdurrer
Copy link
Contributor

@bdurrer bdurrer commented Oct 31, 2021

The main issue with tree-shaking seems to have come from exporting a default module.
The UMD build still exposes an global object Immutable, so it's not affected.

Furthermore, sideEffects: true works by excluding whole modules (files), so the ES6 export must preserve modules in order to enable the end-user's bundler to detect unused parts.

I included an test module, which can be used to see the effects of tree-shaking when using different parts of the library.
The project comes with two analyzers.

The analyzers tell us that only using List results in 34kB (instead of 64kB). However, include a single Map and we are already at 54kB.
One thing I saw was that there are a few cross-references, some of them quite a suprise to the average user. E.g. Map includes OrderedMap because of the sort function. Same with Set and OrderedSet.

I don't think Immutable can ever go super-low, as each collection type comes with an extensive api. A bundler will likely never be able to detect which methods on a collection type are actually used and always has to include the whole class.

@jdeniau
Copy link
Member

jdeniau commented Oct 31, 2021

A possible issue with that might be that the following might not work on strict compiler (possibly with nextjs for example)

import Immutable from 'immutable'

Immutable.Map()

Even if it's not the required way to import immutable, don't you think that this should be breaking and included in a major release?

@bdurrer
Copy link
Contributor Author

bdurrer commented Oct 31, 2021

Even if it's not the required way to import immutable, don't you think that this should be breaking and included in a major release?

err yes, I would say that would cause a major release (if we actually follow semantic versioniong to the letter). Do we have a pattern for that or just collect changes and then decide whether it is a minor or major release? 🤔

@bdurrer bdurrer changed the title ES6 tree-shaking by only using named exports and preserving modules [BREAKING] ES6 tree-shaking by only using named exports and preserving modules Nov 1, 2021
@jdeniau jdeniau linked an issue Nov 12, 2021 that may be closed by this pull request
@bdurrer
Copy link
Contributor Author

bdurrer commented Dec 2, 2021

import Immutable from 'immutable'

Immutable.Map()

BTW the worarkound would be import * as Immutable from 'Immutable';

@jdeniau
Copy link
Member

jdeniau commented Dec 14, 2021

For me it's a 👍 , but I think that we should release this in a 5.x version, as the gain is quite small and the API is breaking.

You can add the 5.0 milestone, if you agree.

@bdurrer bdurrer added this to the 5.0 milestone Dec 20, 2021
@bdurrer
Copy link
Contributor Author

bdurrer commented Dec 20, 2021

I thought a bit about the cyclic dependencies. They seem to only exist because of the sort function on Set and Map and all they do is call OrderedSet(this) / OrderedMap(this). We probably should remove them or find some way to offer the functionality in a disconnected way. It would make tree shaking way more useful

@TaylorClay
Copy link

Wanted to chime in here:
Not to get up on a high horse, but I feel strongly this change should go in (to v5.0 - agreed that it should be a major version bump as it is a breaking change).

Immutable is used by so many devs across many different sizes of projects (NPM has the weekly downloads at 8.75m!).
Many of these devs don't know about / care about bundling & tree shaking.
This is why I think we need to make this change; it would "force" devs to optimize their Immutable imports (unless they're stubborn and do import * as Immutable) after upgrading.

The product I work on professionally is getting an additional 30+ kB on the Critical Path due to transitive dependencies bulk importing Immutable - just to use one or two utilities.

@jdeniau jdeniau changed the base branch from main to 5.x August 24, 2023 09:40
@bdurrer
Copy link
Contributor Author

bdurrer commented Aug 24, 2023

Nice, I had the same idea last week but didn't act yet 😁

I think I will propose another PR to 5.x soonish, which would remove the sort function from Set and Map. We can offer a sort function on top level that returns a sorted collection instead.

IMO the migration path is easy and it resolves the whole cyclic dependency thing.

@jdeniau
Copy link
Member

jdeniau commented Aug 24, 2023

Merging this in 5.x. The TypeScript and Flow types are probably wrong.

Opening #1955 for follow up.

@jdeniau jdeniau merged commit 8dffce4 into 5.x Aug 24, 2023
5 checks passed
@jdeniau jdeniau deleted the tree-shaking branch August 24, 2023 15:42
@jdeniau jdeniau mentioned this pull request Aug 24, 2023
This was referenced Jan 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support tree shaking
3 participants