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

A CLI to compile an entire folder with StyleX #491

Closed
wants to merge 39 commits into from
Closed

A CLI to compile an entire folder with StyleX #491

wants to merge 39 commits into from

Conversation

Jta26
Copy link
Contributor

@Jta26 Jta26 commented Mar 12, 2024

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:

  • Transform every single JS file within the source/ folder with the StyleX Babel plugin and output it at the same relative path in the src/ folder.
  • While transforming it will collect the generated CSS for each file and output a CSS bundle at src/stylex-bundle.css.
  • The transformed JS files should be updated to include an import of the stylex-bundle.css file. (Configurable)

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:

  • Have a watch mode so that only the files that are edited are recompiled, and the generated CSS file is updated accordingly.
  • Can be configured to also pre-compile a given list of node_modules packages and write the compiled files in some locations.
    • Any processed JS files that import these packages, should be updated to rewrite their imports to point to the compiled location.

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

  • The basic configuration options should be possible with both CLI args and with a file config.
  • It should be possible to configure the StyleX Babel plugin without a .babelrc file at the project root. (Next goes into Babel mode if it detect a .babelrc file)
  • It should be possible to run additional Babel transforms in addition to the StyleX Babel plugin

Stretch Goals

  • Avoid recompiling unchanged files between runs (even without watch mode).

Possible tools that can be used:

  • fb-watchman is a node client for watchman. A tool that tracks file changes within a folder
  • chokidar
  • node-watch

Recreated from #412

@facebook-github-bot facebook-github-bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Mar 12, 2024
Copy link

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%)

Copy link

compressed-size: e2e bundles

Size change: 0.00 kB
Total size: 1128.55 kB

View unchanged
Filename: gzip (minify) kB size kB change % change
./apps/rollup-example/.build/bundle.js 1005.20 (10185.36) 0.00 (0.00) 0.0% (0.0%)
./apps/rollup-example/.build/stylex.css 123.34 (773.82) 0.00 (0.00) 0.0% (0.0%)

apps/cli-example/package.json Outdated Show resolved Hide resolved
@nmn
Copy link
Contributor

nmn commented Mar 15, 2024

So @Jta26 Just the external package compilation remaining?

@Jta26
Copy link
Contributor Author

Jta26 commented Mar 17, 2024

So @Jta26 Just the external package compilation remaining?

Yep, working on it now and should have it soon.

@Jta26
Copy link
Contributor Author

Jta26 commented Mar 23, 2024

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

@Jta26
Copy link
Contributor Author

Jta26 commented Mar 24, 2024

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.

@javascripter
Copy link

I'd like importSources config in the CLI so that I can use react-strict-dom with Next.js

@nmn
Copy link
Contributor

nmn commented Apr 4, 2024

@javascripter The CLI let's you pass all the regular config options to the Babel Plugin through a JSON5 file.

@nmn nmn closed this Apr 9, 2024
@nmn nmn deleted the feat/cli branch April 9, 2024 06:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants