Skip to content

Tree shaking while bundling #227

@adnaan1703

Description

@adnaan1703

Is it possible anyhow to implement tree shaking during bundling.

Suppose I have a file say greetings.js:

export const sayHi = (name) => {return `Jarvis says hi to ${name}`};
export const sayBye = (name) => {return `Jarvis says bye to ${name}`};

Now if in my project I am only using sayHi then I want sayBye to be removed from the final bundle which is currently not the case.
Is it possible anyhow to implement this (even if I had to do changes in the config file for the metro bundler).

Activity

rafeca

rafeca commented on Aug 28, 2018

@rafeca
Contributor

Metro currently does not support tree shaking based on module import/export. @mjesun is currently adding first-class support for Metro to understand them and this will eventually allow us to do tree shaking.

Stayed tuned! 😃

ghost

ghost commented on Nov 14, 2018

@ghost

any outcome on tree-shaking ? Looking forward to that.

karanjthakkar

karanjthakkar commented on Nov 26, 2018

@karanjthakkar
Contributor

@rafeca Now that we have experimental support for import/export inside metro, is tree shaking now available out of the box or is there work going on to support it? Anything that we can help with to make this possible?

rafeca

rafeca commented on Nov 27, 2018

@rafeca
Contributor

@karanjthakkar : we're planning to implement some sort of tree shaking (or better said, minification of code based on the es6 module information) during H1 2019.

Based on our internal tests, the most impactful minification in terms of bundle size that can be done is to minify the import/export names, so for example:

// bar.js
export const ANY_VARIABLE_NAME = 'value';
// foo.js
import {ANY_VARIABLE_NAME} from './bar';
console.log(ANY_VARIABLE_NAME);

would get minified to:

// bar.js
exports.a = 'value';
// foo.js
console.log(r('./bar').a);

Afterwards, we're going to be able to do dead code elimination based on the exported values that are not being used anywhere

camdagr8

camdagr8 commented on Mar 22, 2019

@camdagr8

Any movement or resolution on this?

aleclarson

aleclarson commented on May 1, 2019

@aleclarson
Contributor

Is this still slated for H1 2019?

sunnylqm

sunnylqm commented on May 18, 2019

@sunnylqm
Contributor

Jeevan-Kishore

Jeevan-Kishore commented on Aug 8, 2019

@Jeevan-Kishore

Is it supported yet?

12 remaining items

matthew-dean

matthew-dean commented on Nov 18, 2022

@matthew-dean

It's disappointing that Facebook's position is essentially, "bundling the entire import probably won't that much bloat, or add that much performance degradation to your app".

True (maybe), but why not just... not add things that aren't needed? Tree-shaking is an expected feature of any JS bundler, and not having tree shaking violates the Law of Least Surprise. If we use 1 function in, say, a giant hooks library with 1,000 hooks, we expect only that 1 function to show up in our app. If Metro can't provide this, then IMO Metro should not be in the business of bundling and should pair with Vite, Webpack, or other such bundlers to find a solution for React Native devs.

adnaan1703

adnaan1703 commented on Nov 19, 2022

@adnaan1703
Author

Totally agree. The smaller bundle can still be valid even though we performed compression and backed it with Hermes. Currently, we are sending the bundle over HTTP with brotli compression and the underlying engine is Hermes for better performance but that doesn't rule out the use case for tree shaking. Also, I believe folks here undermine the improvement one can get with tree shaking.

When I raised this issue, Haul (predecessor of repack) solved this issue by using webpack. At that time we saw an improvement of around ~49.64% of bundle size.

  • bundle size via metro: 505.84KB
  • bundle size via haul without tree shaking: 537.75KB
  • bundle size via haul with tree shaking: 254.74KB
    Bundle size improvement: haul w/ tree shaking vs metro -> 49.64% gain.
    *This was 2018.

We couldn't go to production with Haul because of a lack of community support and also the bundle it spits breaks our internal system. Our internal diffing logic would have needed overall changes. Also, using scripts to change haste-dependent libraries dynamically seems kind of a hack and is a bit dangerous to send in production.

But now I think we have multiple solutions out there:

  • esbuild with custom tree-shaking plugin
  • repack

Since these tools are now available, it is bound that users with advanced bundling needs will move away from Metro.

kelset

kelset commented on Nov 21, 2022

@kelset
Contributor

btw for those of you using Metro and wanting tree shaking, over at MSFT we have developed a plugin for Metro to basically rely on esbuild for treeshaking: https://github.com/microsoft/rnx-kit/tree/main/packages/metro-serializer-esbuild (guide here: https://microsoft.github.io/rnx-kit/docs/guides/bundling#tree-shaking)

We already use it in prod on a couple projects and saw good bundle size improvements

mannoeu

mannoeu commented on Jul 26, 2023

@mannoeu

Too bad... Ignoring real cases where Tree Shaking is necessary

johnculviner

johnculviner commented on Jun 19, 2024

@johnculviner

Facebook went ahead and wrote their own JavaScript engine (hermes) to try to optimize startup behavior and in my own testing simply having less JavaScript goes a long way in improving startup performance... and dare I say is a lot simpler than writing your own JS engine from scratch 🤯

EvanBacon

EvanBacon commented on Aug 23, 2024

@EvanBacon
Contributor

Went ahead and wrote a version of tree shaking in Expo CLI to get the ball rolling. It can be added to any React Native project by adopting expo/metro-config, babel-preset-expo, and Expo CLI (requires E2E bundler integration).

The implementation is landed on main and it'll ship experimentally in SDK 52 (October 2024). Here are the docs: Tree Shaking in Expo CLI

aleksamrakovic

aleksamrakovic commented on Oct 15, 2024

@aleksamrakovic

Any way to remove .git folder from bundle? Is there any reason why metro do that?

trip8971

trip8971 commented on May 12, 2025

@trip8971

Run a webpack bundle command before the metro bundler's work to achieve the tree-shaking effect. It's worthing noting that you should config webpack external properly.
You can have a try.

BoBoooooo

BoBoooooo commented on Jun 20, 2025

@BoBoooooo

It’s 2025 now. Unfortunately, there is still no metro treeShaking solution. ESBuild & Webpack support treeShaking, but the bundle split solution is different from metro. It’s a one-track mindset. My existing environment is strongly dependent on the Metro ecosystem, and migrating to other bundle solutions will have a high cost. So an official Metro(bundle split) + treeShaking ecosystem is very urgent needed !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @cpojer@camdagr8@rafeca@matthew-dean@sunnylqm

        Issue actions

          Tree shaking while bundling · Issue #227 · facebook/metro