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 #98

Open
deshiknaves opened this issue May 1, 2018 · 7 comments
Open

Tree Shaking #98

deshiknaves opened this issue May 1, 2018 · 7 comments

Comments

@deshiknaves
Copy link

If there are 2 components which both import their respective css files which are imported in an index.js and exported out. Then in another module only one of them is imported, both css files are added to the extracted CSS file. The JS said of it tree shakes the component not being used, but that is not the case of the CSS.

Is there a way to exclude CSS imports that are not being used by the solution?

@lmihaidaniel
Copy link
Collaborator

see rollup-plugin-purifycss maybe this can help

@David-Else
Copy link

I am currently trying to get this working, purgecss looks superior:

https://github.com/FullHuman/rollup-plugin-purgecss

@dferber90
Copy link

I just published a module which enables this (works for inlined CSS only).

I'm glad for any feedback: https://github.com/dferber90/rollup-plugin-postcss-treeshakeable

@dferber90
Copy link

dferber90 commented Sep 8, 2018

We could make this functionality part of rollup-plugin-postcss itself and make it opt-in through an option.

The gist of it is that instead of outputting

var css = ".foo { background: red; }";
export default { foo: "foo__classname_1 " };
import styleInject from "<some-folder>/style-inject/dist/style-inject.es.js";
styleInject(css);

which calls styleInject() directly, we have to emit a module which adds the styles only when classnames are used

import styleInject from "<some-folder>/style-inject/dist/style-inject.es.js";
var cssMap = { foo: "foo__classname_1 " };
var hasRun;
var styles = function styles() {
  if (!hasRun) {
    hasRun = true;
    styleInject(".foo { background: red; }");
  }
  return cssMap;
};

export default styles;

This enables treeshaking. It has the downside that any styles are only applied when the component is actually rendered.

All consumers have to be changed to use the functional export instead

import styles from "./Butler.mod.css";

-const Butler = props => <div className={styles.alfred}>I am Butler</div>;
+const Butler = props => <div className={styles().alfred}>I am Butler</div>;

I tried emitting a module which uses a proxy or getters instead. This would have meant that we can keep the same export. But both approaches were not picked up by treeshaking/dead code elimination unfortunately.

See the example for a walkthrough of how it works.

Sidenote: If you're building the same library with rollup for production, but with webpack for development, then there is a missing piece here. As you now have to transform styles.foo into styles().foo, be aware that there is a missing piece here in case you build the library with Webpack. We need the same transformation there as well. This is not a problem in case your library is only consumed by webpack.

Update: I now created the missing piece: https://github.com/dferber90/style-loader-treeshakeable

@sami616
Copy link

sami616 commented Jun 28, 2020

+1

@sami616
Copy link

sami616 commented Jun 28, 2020

Probably not the greatest solution in the world, but i wonder if simply using commonjs require('./syles.css') inside your component might work too?

@adi518
Copy link

adi518 commented Jul 24, 2020

What about prepending /*#__PURE__*/ to styleInject? I actually tried this (modified the dist with this fix) and my tree-shaking check with agadoo passes. The only problem is when I try to add this magic comment myself, the entire styleInject function gets stripped away (started issue #293).

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

No branches or pull requests

6 participants