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

Optimize usage of styles exported from a file and used elsewhere #729

Open
nmn opened this issue Oct 9, 2024 · 0 comments
Open

Optimize usage of styles exported from a file and used elsewhere #729

nmn opened this issue Oct 9, 2024 · 0 comments
Labels
enhancement New feature or request

Comments

@nmn
Copy link
Contributor

nmn commented Oct 9, 2024

It is a common pattern for developers to define styles using stylex.create in a file and export them and then import and use those styles elsewhere.

export const styles = stylex.create(...)

However we've always discouraged this pattern because it makes it almost impossible to detect unused styles at compile time. Could we fix this problem?

The Task

We should implement an optimisation to that detects and removes unused styles from both the Javascript and the CSS. Here's an approach that might work:

Enforce default exports from .stylex.js files only

We could enforce that stylex.create calls are only ever exported as default exports from files with a .stylex.js extension. (we would need to update our enforce-extension lint rule to allow this).

The compiler marks all CSS rules extracted from these files with a unique ID

When extracting styles from the default export of .stylex.js file, we could mark every CSS rule to indicate that we don't know whether it is used or not. The InjectableStyle type can be extended like so:

type InjectableStyle = {
  +priority: number,
  +ltr: string,
  +rtl: null | string,
  +usageUnkown?: string, // unique ID
};

Detect usage of styles imported from .stylex.js files

When the default export is imported from a .stylex.js we can statically check which keys have been used. We can then add metadata to the extracted list of styles from that file to mark the relevant styles as "used".

const marker: InjectableStyle = {
  usageMarker: // unique ID of style that was used.
  priority: -1,
  ltr: '',
  rtl: null,
  
};

Remove unused style objects before de-duplicating styles

Using the usageUnknown and usageMarker keys, we can remove any styles that are not used before we deduplicate the list of all styles collected after compilation. If the same style was used elsewhere, that would exist in the list without the usageUnkown key anyway and would be kept in the final CSS.

Leverage tree-shaking

The steps above will help remove unused styles from the generated CSS, but to remove the unused classNames from the Javascript is more challenging, specially for a per-file transformation like StyleX.

However, we can generate code that various bundlers should be able to tree-shake.

To enable tree-shaking, we can split the default export of stylex.create from a .stylex.js file to create a separate named export for each "rule" within the stylex.create. On the flip-side we will also have to split the default imports from .stylex.js files.

Just doing this should help bundlers that support tree-shaking to detect and remove the unused rules.

@nmn nmn added the enhancement New feature or request label Oct 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant