How the Astryx CLI Build Command Handles StyleX Source Builds vs. Pre‑Compiled CSS

The Astryx CLI build command compiles TypeScript/StyleX source files into CSS via a dedicated extraction script, but skips that expensive step and reuses existing CSS files when they are already present.

The @astryxdesign build pipeline in the facebook/astryx repository separates StyleX source compilation from CSS generation to maximize cache efficiency in CI environments. Understanding how the CLI distinguishes between raw .stylex.ts sources and pre‑built stylesheets helps developers optimize their build times and debug packaging issues.

The Two‑Phase Build Architecture

Phase 1: TypeScript and StyleX Source Compilation

The build process begins in packages/cli/clients/cli/commands/build.mjs, which delegates to the ensure‑core‑built helper at packages/cli/clients/cli/commands/ensure-core-built.mjs.

This phase:

  • Runs pnpm build across the monorepo
  • Transpiles .ts/.tsx files to JavaScript
  • Emits intermediate .stylex.ts files containing raw StyleX definitions to each package's dist/ directory

These .stylex.ts files are not yet CSS—they are JavaScript modules that export style objects that must be transformed.

Phase 2: CSS Extraction via build‑css.mjs

Once TypeScript compilation completes, control passes to scripts/build-css.mjs. This script performs the actual StyleX-to-CSS conversion:

// scripts/build-css.mjs (conceptual flow)
import { extract } from '@astryxdesign/build';

// Walk dist/ tree, find .stylex.ts modules
// Extract declarative StyleX objects → plain CSS rules
// Write single stylesheet per package (e.g., packages/core/dist/astryx.css)

The @astryxdesign/build extractor (implemented in packages/build/src/extract.mjs) parses the style objects and generates optimized CSS. The CLI then updates each package's package.json with a stylex:css field pointing to the compiled stylesheet location.

How Pre‑Compiled CSS Short‑Circuits the Pipeline

The CLI avoids redundant work through a deterministic check in the ensure‑core‑built helper:

// packages/cli/clients/cli/commands/build.mjs (simplified)
import { ensureCoreBuilt } from './ensure-core-built.mjs';
import { runBuildCss } from '../../scripts/build-css.mjs';

export async function run() {
  await ensureCoreBuilt();               // Step 1: Compile TS sources
  
  if (!await cssAlreadyExists()) {       // Step 2: Check for cached CSS
    await runBuildCss();                 // Step 2b: Extract only if needed
  }
  
  // Step 3: Theme packaging, manifest generation, tarball creation
}

When cssAlreadyExists() finds the expected CSS file (e.g., packages/core/dist/astryx.css), the CLI prints:


CSS already present – skipping build-css

This optimization is critical for parallel CI jobs and incremental builds. Cached dist/ directories from previous runs allow the command to bypass the relatively expensive StyleX parsing pass entirely.

Final Packaging and Theme Pipeline

With CSS guaranteed present—whether freshly extracted or pre‑existing—the CLI executes the @astryxdesign/build theme pipeline at packages/cli/api/theme/build/build.mjs. This stage:

  • Bundles compiled CSS with JavaScript assets
  • Generates the final publishable .tgz archive
  • Updates the workspace lockfile

The separation between source transformation and CSS extraction means the theme pipeline operates on finalized artifacts without needing to distinguish their origin.

Key Implementation Files

Purpose File Path
CLI build command orchestrator packages/cli/clients/cli/commands/build.mjs
Core compilation guarantee helper packages/cli/clients/cli/commands/ensure-core-built.mjs
Post‑build CSS extraction script scripts/build-css.mjs
Theme packaging pipeline packages/cli/api/theme/build/build.mjs
StyleX extraction library packages/build/src/extract.mjs

Build Command Examples


# Full build: compile TypeScript, extract StyleX, generate CSS

$ astryx build

# Fast path: skip CSS extraction when dist/ is cached

# (automatically detected; manual flag for explicit control)

$ astryx build --skip-css

Summary

  • Raw StyleX sources (.stylex.ts) require processing through scripts/build-css.mjs using the @astryxdesign/build extractor
  • Pre‑compiled CSS is detected via file existence checks in ensure-core-built.mjs, enabling cache‑friendly incremental builds
  • The CLI's two‑phase architecture separates TypeScript compilation from CSS generation to maximize parallelism and avoid redundant work
  • Final packaging occurs through the theme pipeline at packages/cli/api/theme/build/build.mjs, regardless of CSS origin

Frequently Asked Questions

How does Astryx detect whether CSS needs to be rebuilt?

The ensure-core-built.mjs helper checks for the presence of expected CSS files in each package's dist/ directory. If packages/*/dist/*.css exists and matches the expected naming convention, the CLI assumes the CSS is current and bypasses the build-css.mjs extraction step.

Can I force CSS regeneration even when cached files exist?

The CLI supports a --skip-css flag for explicit control (used inversely to skip generation). To force regeneration in environments with partial caches, clear the dist/ directories before running astryx build, or use environment-specific CI configurations that scope cache keys to source file hashes.

What format do the intermediate .stylex.ts files use?

These files export JavaScript objects containing StyleX style definitions—essentially the raw output of the StyleX transformer before CSS extraction. The @astryxdesign/build extractor in packages/build/src/extract.mjs consumes these objects and emits atomic CSS rules with hashed class names.

Where does the final CSS get referenced for downstream consumers?

After extraction completes, the CLI updates each package's package.json with a stylex:css field pointing to the generated stylesheet path. This metadata allows dependent packages to discover and bundle the CSS without hardcoding paths.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →