---
robots: noindex, nofollow
tags: pitch
---
For instructions on shaping a project see here: [Shaping a Project](/kX02SXVbS6KzMOQd56i6Cg)
# Improve react-northstar performance (css expand during build time)
## Problem
Performance of CSS-in-JS is the most complicated question. Currently we have a lot of requests from Teams side to improve performance somehow immediately as Fluent components are widely in Teams Modular Packages.
## Appetite
If we will be able to reach reasonable performance level it can comparable with proposed CSS solution.
## Solution
The solution is separated to three parts:
- improve Fela performance
- improve Fela plugins performance
- try to pregenerate some rules at runtime
### Fela tweaks
Fela by itself is quite fast, but I was able to find slow functions there and improved perfomance (improves render time for 5-7%) of one of them.
Goal there to merge existing PR [(robinweser/css-in-js-utils#11)](https://github.com/robinweser/css-in-js-utils/pull/11) and try to find out other places to improve.
### Fela plugins performance
We have already done optimisations there, for example we changed a dependency in one of plugins ([microsoft/fluent-ui-react#1925](https://github.com/microsoft/fluent-ui-react/pull/1925)) and gained 10% improvement.
Currently our slowest plugin is `felaExpandCssShorthandsPlugin` what expands shorthand properties to longhand (`padding => padding-left, padding-right, etc.`):

The worst thing that we can't improve its performance in anyway except of its removal.
#### Step 1: create helpers
_So how we are going to expand properties?_ Via helpers like [`padding()`](https://polished.js.org/docs/#padding):
```diff
const styles = {
- padding: '5px',
+ ...padding('5px'),
}
```
In this case we can keep existing behavior and disable that plugin, that will give us around 25% gain. The set of properties is limited to:
- `border`, `borderTop`, `borderRight`, `borderBottom`, `borderLeft` `borderWidth`, `borderStyle`, `borderColor`
- `padding`, `margin`
- `outline`
- `flex`
#### Step 2: babel transform
To avoid runtime costs as each helper is a function I propose to write Babel plugin to tranform them:
```diff
const styles = {
- ...padding('5px'),
+ paddingLeft: '5px',
+ paddingBottom: '5px',
+ paddingRight: '5px',
+ paddingTop: '5px',
}
```
This will allow us to the same job as the expand plugin without any runtime cost.
### Pregenerate styles
The next step is try to pregenerate some of static styles. Some of our rules are static and can be transformed during build time:
```js
const styles = {
paddingLeft: token.padding, // dynamic
paddingRight: '5px', // static
}
```
During `renderRule()` Fela:
- runs `generateDeclarationReference()` to create a key to for cache entry
- runs `cssifyDeclaration()` to tranform JS styles to CSS values
- generates classes, inserts to a cache and notifies DOM consumers
_What if we will be to omit first & second stages?_
```js
const styles = {
__a: { declaration: 'padding-right5px', css: 'padding-right: 5px' },
}
```
And in custom enhancer handle these cases. At least it worth trying.
### Risks (Rabbit holes)
#### Fela tweaks
__Risk:__ Robin will not accept my PR
__Solution:__ Finalize enhancer on our side
#### Fela plugins performance
__Risk:__ Development of Babel plugin can take too many time
__Solution:__ Finish first step and only then switch to second
#### Pregenerate styles
__Risk:__ It will not work
__Solution:__ Ensure that merging of objects will continue to work
```js
const styles = (props) => ({
display: 'block',
...props.inline && { display: 'inline-block' }
})
```
__Risk:__ There will be no perf improvement
__Solution:__
- Measure amount of static styles
- Test perf improvements before trying to automate transforms
### Out of scope (No-gos)
???