facebook / stylex

StyleX is the styling system for ambitious user interfaces.
https://stylexjs.com
MIT License
8.22k stars 303 forks source link

Feat/cli #528

Closed nmn closed 2 months ago

nmn commented 2 months ago

What changed / motivation ?

StyleX needs a bundler integration to work correctly. It also depends on Babel. However, this can be burden when trying to integrate into various projects built with project starters like Next.js, Solid Start and create-react-app. These projects have a complex bundler setup and it can be hard to integrate into them correctly. In some cases, like Next, the tooling may be written in Rust where an integration of the Babel plugin is impossible.

In order to provide a clean and reliable escape hatch for these scenarios, we should have a CLI that transforms an entire folder of JS files and outputs the resulting CSS file. (Tools like Tailwind and PandaCSS similarly side-step the built-in bundler because of how hard it is to integrate)

Expected Behaviour

For this example, consider a Next.js app configured to use the src/ folder with a src/app/ within that contains actual routes. When using the CLI, you'd be able to make another folder called, say, source/ and gitignore src/ folder. The source/ folder would contain all the same files that would normally be defined within the src/ folder, but you'd be able to use StyleX.

The CLI will then:

With this process, the StyleX CLI would run first and generate an src/ folder with your actual source code. After this, the usual next dev script will be able to take over and run as usual.

Additionally, the CLI should also:

Finally, there are a few requirements for the configuration (This is probably a lot of the work):

Stretch Goals

Possible tools that can be used:

Recreated from https://github.com/facebook/stylex/pull/412

nmn commented 2 months ago

Okay, so what I made now kinda works. There's a bug somewhere (probably in my code) that makes the hashes for styles that are from external .stylex files reference non-existing variables.

styles like this from open-props

import {colors} from '@stylexjs/open-props/colors.stylex';
const styles = stylex.create({
  h2Color: {
    color: colors.green
  }
});

...

<h2 {...stylex.props(styles.h2Green)}></h2>

Will be transformed into

<h2 class="x3ifasef ..." >

and the css will look like

.x3ifasef:not(#\#):not(#\#):not(#\#){color:var(--x1masbj0)}

--x1masbj0 should be a reference to the variable colors.green, but it doesn't > reference anything and isn't a defined variable. The actual variable created in > colors.stylex.js is something entirely different, and also exists in the generated css.

Something is not connected between them and I cannot figure out why.

nmn commented 2 months ago

Okay so I figured it out and got it working

Babel is doing DFS, and the plugin I made was selecting on ImportDeclaration, but StyleX runs on Program, so it seems like it runs first regardless of the order of the plugins. And I think StyleX determines it's hashes based on the file paths, so to find the hash it would look at the import and hash @stylexjs/open-props/lib/colors.stylex, which isn't what gets hashed when the open-props module is copied over and compiled.

it's hashing {$rootDir}/${config.output}/stylex_compiled_modules/@stylexjs/open-props/lib/colors.stylex when the plugin passes over the file, which is not equal to ${rootDir}/@stylexjs/open-props/lib/colors.stylex when it hashes the import.

I fixed the issue by also using Program in my plugin and making it run before the StyleX plugin.

github-actions[bot] commented 2 months ago

compressed-size: runtime library

Size change: 0.00 kB Total size: 2.52 kB

View unchanged | Filename: gzip (minify) | kB size | kB change | % change | | :--- | :--- | :--- | :--- | | `./packages/stylex/lib/stylex.js` | **1.04** (3.22) | **0.00** (0.00) | **0.0%** (0.0%) | | `./packages/stylex/lib/StyleXSheet.js` | **1.48** (3.75) | **0.00** (0.00) | **0.0%** (0.0%) |
github-actions[bot] commented 2 months ago

compressed-size: e2e bundles

Size change: 0.00 kB Total size: 1128.74 kB

View unchanged | Filename: gzip (minify) | kB size | kB change | % change | | :--- | :--- | :--- | :--- | | `./apps/rollup-example/.build/bundle.js` | **1005.32** (10185.35) | **0.00** (0.00) | **0.0%** (0.0%) | | `./apps/rollup-example/.build/stylex.css` | **123.42** (774.34) | **0.00** (0.00) | **0.0%** (0.0%) |
larsfoll commented 2 months ago

@nmn Without wanting to put pressure, do you have a rough idea when this would be released?

At work we might decide to temporarily opt-out of the SWC compiler from Next to already allow the usage of stylex - but of course would prefer not to.

Already thanks for the great work!

nmn commented 2 months ago

@larsfoll There are some complex edge-cases with the CLI so we don't have an estimate yet.