facebook / facebook/stylex

Optimize usage of styles exported from a file and used elsewhere

Open
#729 0 comments 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
JavaScript
Stars
10.3k
Forks
481
Avg merge
3d 8h
Merged PRs (30d)
13

Description

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.

```ts
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:

```ts
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".

```ts
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.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.