# Performance Considerations When Using Astryx Components: A Technical Guide to facebook/astryx

> Boost Astryx performance with compile-time CSS, ResizeObserver, WebGL, and virtualization. Avoid inline styles and ensure SSR hydration for faster React apps.

- Repository: [Meta/astryx](https://github.com/facebook/astryx)
- Tags: performance
- Published: 2026-07-15

---

**Optimize Astryx applications by leveraging StyleX compile-time CSS, the shared ResizeObserver singleton, WebGL for dense visualizations, and built-in virtualization, while avoiding inline styles and ensuring consistent SSR hydration.**

The `facebook/astryx` repository provides a high-performance component library designed for building fast internal tools. While Astryx is architected for speed with features like zero-runtime CSS and GPU-accelerated charts, achieving optimal rendering requires understanding specific implementation patterns. This guide examines critical performance considerations when using Astryx components, referencing actual source files and implementation details from the codebase.

## Compile-Time Styling with StyleX

Astryx relies on **StyleX** to compile CSS at build time, eliminating the heavy JavaScript-based style-injection loops common in other UI libraries. According to the source in [`packages/core/README.md`](https://github.com/facebook/astryx/blob/main/packages/core/README.md), this approach generates static class names that incur **zero runtime style calculations** and benefit from better browser caching.

Never use `style={{…}}` for dynamic styling. Instead, use `stylex.props()` or `stylex.when.*` helpers to ensure StyleX compiles rules ahead-of-time.

```tsx
import {stylex} from '@stylex/react';
import {Button} from '@astryxdesign/core';

const primary = stylex.create({
  base: { padding: '8px 16px', borderRadius: 4 },
  hover: stylex.when.ancestor(':hover', {
    backgroundColor: 'var(--color-primary-hover)',
  }),
});

export function PrimaryButton(props) {
  return <Button {...stylex.props(primary.base, primary.hover)} {...props} />;
}

```

## Shared ResizeObserver Singleton

Astryx centralizes every `ResizeObserver` into a **shared singleton** implemented in [`packages/core/src/observer/ResizeObserverSingleton.ts`](https://github.com/facebook/astryx/blob/main/packages/core/src/observer/ResizeObserverSingleton.ts) (referencing changelog entry #1990 in [`packages/core/CHANGELOG.md`](https://github.com/facebook/astryx/blob/main/packages/core/CHANGELOG.md)). This pattern prevents excessive layout thrashing and memory pressure that would occur if individual components created separate native observers.

For custom resize handling, use the `useResizeObserver` hook from the core package, which automatically registers with the singleton.

```tsx
import {useResizeObserver} from '@astryxdesign/core';

export function AutoFitBox({children}) {
  const ref = useResizeObserver((entry) => {
    console.log('size changed', entry.contentRect);
  });

  return <div ref={ref}>{children}</div>;
}

```

## GPU-Accelerated Chart Rendering

The `@astryxdesign/charts` package utilizes **WebGL** for high-density visualizations like heatmaps and scatter plots. As implemented in [`packages/charts/src/marks/heatmapGL.tsx`](https://github.com/facebook/astryx/blob/main/packages/charts/src/marks/heatmapGL.tsx), WebGL executes thousands of points in a single GPU draw call, storing memory in GPU buffers rather than reallocating on each render.

Only enable WebGL for datasets larger than a few hundred points. For smaller datasets, the overhead of creating a GL context outweighs the benefits—use the standard `heatmap` mark instead.

```tsx
import {HeatmapGL, Heatmap} from '@astryxdesign/charts';

export function AdaptiveHeatmap({data}) {
  const useGL = data.length > 500;
  return useGL ? <HeatmapGL data={data} /> : <Heatmap data={data} />;
}

```

## Virtualization for Large Lists and Tables

Components such as `Table`, `List`, and `TreeList` automatically **virtualize** off-screen rows using logic from [`packages/core/src/Table/TableVirtualizer.ts`](https://github.com/facebook/astryx/blob/main/packages/core/src/Table/TableVirtualizer.ts). This technique limits DOM node count and reduces event-listener allocation, keeping paint times low for massive datasets.

Maintain constant row heights when possible. Variable heights force the virtualizer to recompute layout on every scroll, degrading performance.

```tsx
import {Table} from '@astryxdesign/core';

export function LargeTable({rows}) {
  return (
    <Table
      data={rows}
      rowHeight={40}
      virtualized
    />
  );
}

```

## Server-Side Rendering and Hydration

Astryx ships with **SSR-ready components** that pre-generate StyleX classes on the server, delivering fully-styled HTML snapshots to the client. As documented in `docs/SSR‑hydration.mdx`, hydration cost remains minimal because the client only attaches event listeners without re-computing styles.

Avoid conditional rendering that alters the component tree between server and client, as this triggers a full re-render during hydration.

## Memoization of Heavy Computations

For expensive calculations like color scales for large charts, Astryx provides the `useMemoizedValue` hook found in [`packages/core/src/hooks/useMemoizedValue.ts`](https://github.com/facebook/astryx/blob/main/packages/core/src/hooks/useMemoizedValue.ts). This prevents unnecessary recalculations on every render cycle.

Wrap heavy `map`, `reduce`, or `filter` operations that depend on large datasets with this hook.

```tsx
import {useMemoizedValue} from '@astryxdesign/core';
import {ColorScale} from '@astryxdesign/charts';

export function ColorfulBarChart({values}) {
  const scale = useMemoizedValue(() => new ColorScale(values), [values]);
  return <BarChart data={values} colorScale={scale} />;
}

```

## Accessibility Without Performance Penalty

Astryx embeds ARIA attributes directly into rendered markup. Because these are plain HTML attributes, there is **no runtime cost** beyond the initial render, and they do not interfere with GPU-accelerated rendering paths. The implementation in [`packages/core/src/VisuallyHidden/VisuallyHidden.tsx`](https://github.com/facebook/astryx/blob/main/packages/core/src/VisuallyHidden/VisuallyHidden.tsx) demonstrates this zero-cost approach to accessibility.

## Bundle Optimization and Tree-Shaking

The monorepo uses **PNPM workspaces** with ESM output, configured in [`pnpm-workspace.yaml`](https://github.com/facebook/astryx/blob/main/pnpm-workspace.yaml). Import only needed components; unused modules are dropped by the bundler, reducing initial load time.

Prefer named imports (`import {Button} from '@astryxdesign/core'`) over wildcard imports to ensure effective tree-shaking.

## Summary

- **StyleX compilation** eliminates runtime CSS calculations through build-time static class generation.
- The **ResizeObserver singleton** prevents memory leaks and layout thrashing by sharing one native observer across all components.
- **WebGL rendering** in charts provides GPU acceleration for large datasets, but should be disabled for small data to avoid context overhead.
- **Virtualization** automatically limits DOM size for lists and tables, especially effective with constant row heights.
- **SSR hydration** requires stable component trees between server and client to avoid re-renders.
- **useMemoizedValue** caches expensive computations to prevent redundant processing during render cycles.
- **Tree-shaking** works efficiently with named imports in the PNPM workspace structure.

## Frequently Asked Questions

### How does Astryx minimize runtime style calculation overhead?

Astryx uses StyleX to compile all CSS at build time, generating static class names that require zero runtime computation. According to [`packages/core/README.md`](https://github.com/facebook/astryx/blob/main/packages/core/README.md), this approach eliminates the JavaScript-based style injection loops found in traditional CSS-in-JS libraries, resulting in better caching and faster initial loads.

### When should I use WebGL charts versus standard SVG charts in Astryx?

Use WebGL components like `HeatmapGL` for datasets exceeding a few hundred points, as the GPU can render thousands of points in a single draw call. For smaller datasets, use standard SVG marks to avoid the overhead of WebGL context creation, as implemented in [`packages/charts/src/marks/heatmapGL.tsx`](https://github.com/facebook/astryx/blob/main/packages/charts/src/marks/heatmapGL.tsx).

### Does virtualization in Astryx tables require fixed row heights?

While virtualization works with variable heights, optimal performance requires constant row heights. The `TableVirtualizer` logic in [`packages/core/src/Table/TableVirtualizer.ts`](https://github.com/facebook/astryx/blob/main/packages/core/src/Table/TableVirtualizer.ts) recomputes layout less frequently when `rowHeight` remains consistent, reducing scroll jank in large tables.

### Are there any performance penalties for using Astryx's accessibility features?

No. Astryx embeds ARIA attributes as plain HTML markup without runtime overhead. As shown in [`packages/core/src/VisuallyHidden/VisuallyHidden.tsx`](https://github.com/facebook/astryx/blob/main/packages/core/src/VisuallyHidden/VisuallyHidden.tsx), these attributes do not interfere with GPU-accelerated rendering paths or add computational cost beyond the initial render.