[feature] Add stylex.env for compile time constants
What changed / motivation ?
StyleX already supports stylex.defineConsts but this has a few limitations and trade-offs:
- It can only store individual values. It cannot store objects with different values for different pseudo-classes and media queries for example.
- It generates CSS variables at compile time, which are then inlined at bundle-time. This means it generates different className hashes than what would've been generated if the value was used directly.
This PR introduces a new feature called stylex.env. This is fundamentally a very simple feature that is similar to how process.env is already used in many applications. It allows you to configure the stylex babel plugin with constants that are inlined before the stylex compiler runs. It can also contain arbitrary values.
The main trade-off here is that since this is something that is part of the babel config, every change to the constants provided will invalidate the entire cache of stylex compilation.
Additional Context
Some basic tests have been included. Will add more tests with more advanced use-cases.
Pre-flight checklist
- [x] I have read the contributing guidelines Contribution Guidelines
- [x] Performed a self-review of my code
workflow: benchmarks/perf
Comparison of performance test results, measured in operations per second. Larger is better.
[email protected] compare node ./compare.js /tmp/tmp.7a961Wr1QB /tmp/tmp.razEDnEJ92
| Results | Base | Patch | Ratio | |
|---|---|---|---|---|
| babel-plugin: stylex.create | ||||
| · basic create | 642 | 629 | 0.98 | - |
| · complex create | 69 | 69 | 1.00 | |
| babel-plugin: stylex.createTheme | ||||
| · basic themes | 464 | 457 | 0.98 | - |
| · complex themes | 43 | 43 | 1.00 |
workflow: benchmarks/size
Comparison of minified (terser) and compressed (brotli) size results, measured in bytes. Smaller is better.
[email protected] compare node ./compare.js /tmp/tmp.HI98H2llcF /tmp/tmp.t4DpFyUZO5
| Results | Base | Patch | Ratio | |
|---|---|---|---|---|
| @stylexjs/stylex/lib/cjs/stylex.js | ||||
| · compressed | 1,282 | 1,310 | 1.02 | + |
| · minified | 4,025 | 4,084 | 1.01 | + |
| @stylexjs/stylex/lib/cjs/inject.js | ||||
| · compressed | 1,223 | 1,223 | 1.00 | |
| · minified | 3,216 | 3,216 | 1.00 | |
| benchmarks/size/.build/bundle.js | ||||
| · compressed | 496,650 | 496,650 | 1.00 | |
| · minified | 4,847,840 | 4,847,840 | 1.00 | |
| benchmarks/size/.build/stylex.css | ||||
| · compressed | 99,853 | 99,853 | 1.00 | |
| · minified | 747,541 | 747,541 | 1.00 |
Some test failures. Let's also discuss whether shareable functions will fit in here as well or under a different API