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

Tree-shaking not working #688

Open
kuldeepkeshwar opened this issue Jul 27, 2020 · 3 comments
Open

Tree-shaking not working #688

kuldeepkeshwar opened this issue Jul 27, 2020 · 3 comments

Comments

@kuldeepkeshwar
Copy link

@kuldeepkeshwar kuldeepkeshwar commented Jul 27, 2020

layout-ui is bundled using mircobundle and produces cjs/esm/umd bundles.

While using any of named export from layout-ui, the final application bundle contains whole esm bundle from layout-ui.
e.g

import React from "react";
import { Stack } from "layout-ui";

export default function App() {
  return (
      <Stack gap="2rem" align="center">
        <div>Item 1</div>
        <div>Item 2</div>
      </Stack>
  );
}

In above example, ideally it should only bundle code for Stack.

@marvinhagemeister
Copy link
Collaborator

@marvinhagemeister marvinhagemeister commented Jul 27, 2020

That's because it's not possible for current bundlers/minifiers to detect if styled() has side-effects or not. To ensure that those are tree-shaken they need to be prepended with a hint that they are in fact pure. This can be done by adding /* #__PURE__ */ as a comment just before the function call.

const Foo = /* #__PURE__ */ styled("div")`
  color: red;
`

For a babel plugin that does inserts these comments check out:

@kuldeepkeshwar
Copy link
Author

@kuldeepkeshwar kuldeepkeshwar commented Jul 27, 2020

just trying to understand it in detail.
For example

// library.js
function useMyHook(){...} // current bundlers/minifiers don't know whether useMyHook is pure or not 
export function ComponentWithHook(){ 
 const [a,b] = useMyHook();
 // do something with a & b
...
}
export function IAmPure(){...}
// app1.js
import {ComponentWithHook} from 'library';
render(<ComponentWithHook/>)
// app2.js
import {IAmPure} from 'library';
render(<IAmPure/>)

In above case

  • App1 will bundle whole library
  • App1 will bundle ComponentWithHook & useMyHook
  • App2 will bundle only IAmPure
  • App2 will bundle IAmPure & useMyHook
  • App2 will bundle whole library

@marvinhagemeister ^ which option(s) is correct ? 🙂

@marvinhagemeister
Copy link
Collaborator

@marvinhagemeister marvinhagemeister commented Jul 27, 2020

@kuldeepkeshwar Maybe just try it out?

The top level exports aren't the only requirement for tree-shaking. Tree-shaking is a subclass of dead code elimination (=DCE) and it's only possible to remove something when the minifier/bundler is 100% certain that removing it won't alter the program. For todays bundlers this usually translates to checking if the code in question has no side-effects. If the body of a function can't be proven to be pure and is used somewhere, it won't be removed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.