StyleX:Meta推出的高性能零运行时CSS-in-JS解决方案

简介

StyleX 是由 Meta 开发的零运行时 CSS-in-JS 解决方案,在构建时将样式编译为静态 CSS,消除运行时开销。

核心特性

  • 零运行时开销 -- 构建时编译为静态 CSS
  • 类型安全 -- 完整的 TypeScript 支持
  • 原子化 CSS -- 自动生成原子化类名,最小化包体积
  • 开发体验 -- 热重载、错误提示、工具链集成

快速开始

安装

复制代码
npm install @stylexjs/stylex
npm install -D @stylexjs/rollup-plugin

Vite 配置

复制代码
// vite.config.js
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import stylexPlugin from "@stylexjs/rollup-plugin";

export default defineConfig({
  plugins: [
    stylexPlugin({
      dev: true,
      runtimeInjection: true,
      genConditionalClasses: true,
      fileName: "stylex.css",
      unstable_moduleResolution: {
        type: "commonJS",
        rootDir: process.cwd(),
      },
    }),
    react(),
  ],
});

基础用法

创建样式

复制代码
import * as stylex from "@stylexjs/stylex";

// 简单的样式定义
const styles = stylex.create({
  button: {
    padding: 16,
    margin: 8,
    borderRadius: 4,
    borderWidth: 1,
    borderStyle: "solid",
    borderColor: "#ccc",
    backgroundColor: "#f0f0f0",
    cursor: "pointer",
    fontSize: 16,
  },
  primary: {
    backgroundColor: "#007bff",
    borderColor: "#007bff",
    color: "white",
  },
});

function StyleXButton({ variant, children }) {
  const buttonProps = stylex.props(
    styles.button,
    variant === "primary" && styles.primary
  );

  return <button {...buttonProps}>{children}</button>;
}

响应式设计

复制代码
import * as stylex from "@stylexjs/stylex";

const responsiveStyles = stylex.create({
  container: {
    padding: 16,
    "@media (max-width: 768px)": {
      padding: 8,
    },
    "@media (min-width: 1024px)": {
      padding: 32,
    },
  },
});

主题系统

复制代码
//tokens.stylex.js
import * as stylex from "@stylexjs/stylex";

// 定义主题变量
export const tokens = stylex.defineVars({
  primaryColor: "#007bff",
  backgroundColor: "#ffffff",
  textColor: "#333333",
  spacing: "16px",
});

// 暗色主题
export const darkTheme = stylex.createTheme(tokens, {
  primaryColor: "#0d6efd",
  backgroundColor: "#1a1a1a",
  textColor: "#ffffff",
  spacing: "16px",
});

import * as stylex from "@stylexjs/stylex";
import { tokens, darkTheme } from "./tokens.stylex.js";

// 使用主题
const themedStyles = stylex.create({
  card: {
    backgroundColor: tokens.backgroundColor,
    color: tokens.textColor,
    padding: tokens.spacing,
  },
});

function ThemedCard({ isDark, children }) {
  const themeProps = stylex.props(isDark && darkTheme);
  const cardProps = stylex.props(themedStyles.card);

  return (
    <div {...themeProps}>
      <div {...cardProps}>{children}</div>
    </div>
  );
}

实际应用示例

卡片组件

复制代码
const cardStyles = stylex.create({
  card: {
    backgroundColor: "white",
    borderRadius: 8,
    boxShadow: "0 2px 8px rgba(0, 0, 0, 0.1)",
    overflow: "hidden",
    transition: "transform 0.2s ease",
    ":hover": {
      transform: "translateY(-2px)",
    },
  },
  header: {
    padding: 16,
    borderBottom: "1px solid #e9ecef",
  },
  content: {
    padding: 16,
  },
});

function Card({ title, children }) {
  const cardProps = stylex.props(cardStyles.card);
  const headerProps = stylex.props(cardStyles.header);
  const contentProps = stylex.props(cardStyles.content);

  return (
    <div {...cardProps}>
      {title && (
        <div {...headerProps}>
          <h3>{title}</h3>
        </div>
      )}
      <div {...contentProps}>{children}</div>
    </div>
  );
}

表单组件

复制代码
const formStyles = stylex.create({
  input: {
    width: "100%",
    padding: "8px 12px",
    border: "1px solid #ddd",
    borderRadius: 4,
    ":focus": {
      outline: "none",
      borderColor: "#007bff",
      boxShadow: "0 0 0 2px rgba(0, 123, 255, 0.25)",
    },
  },
  error: {
    borderColor: "#dc3545",
  },
  button: {
    padding: "12px 24px",
    backgroundColor: "#007bff",
    color: "white",
    border: "none",
    borderRadius: 4,
    cursor: "pointer",
    ":hover": {
      backgroundColor: "#0056b3",
    },
  },
});

工具集成

高级 Vite 配置

复制代码
// vite.config.js
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import stylexPlugin from "@stylexjs/rollup-plugin";

export default defineConfig({
  plugins: [
    react(),
    stylexPlugin({
      dev: process.env.NODE_ENV === "development",
      genConditionalClasses: true,
      fileName: "stylex.css",
      minify: process.env.NODE_ENV === "production",
      // 自定义类名生成
      classNamePrefix: "sx",
      // 启用样式去重
      unstable_moduleResolution: {
        type: "commonJS",
        rootDir: process.cwd(),
      },
    }),
  ],
  build: {
    // 确保 CSS 被正确提取
    cssCodeSplit: true,
    rollupOptions: {
      output: {
        assetFileNames: (assetInfo) => {
          if (assetInfo.name === "stylex.css") {
            return "assets/stylex.[hash].css";
          }
          return "assets/[name].[hash][extname]";
        },
      },
    },
  },
});

TypeScript 支持

复制代码
// stylex.d.ts
declare module "@stylexjs/stylex" {
  export function create<T extends Record<string, any>>(
    styles: T
  ): { [K in keyof T]: string };
  export function defineVars<T extends Record<string, string | number>>(
    vars: T
  ): T;
  export function createTheme<T>(baseTheme: T, overrides: Partial<T>): string;
  export default function stylex(
    ...styles: (string | false | null | undefined)[]
  ): string;
}

最佳实践

样式组织

复制代码
// tokens.js - 设计令牌
export const tokens = stylex.defineVars({
  colorPrimary: "#007bff",
  colorSecondary: "#6c757d",
  spacingS: "8px",
  spacingM: "16px",
  spacingL: "24px",
  fontSizeS: "12px",
  fontSizeM: "14px",
  borderRadius: "4px",
});

// Button.stylex.js - 组件样式
import { tokens } from "./tokens";

export const buttonStyles = stylex.create({
  base: {
    padding: `${tokens.spacingS} ${tokens.spacingM}`,
    fontSize: tokens.fontSizeM,
    borderRadius: tokens.borderRadius,
    border: "none",
    cursor: "pointer",
  },
  primary: {
    backgroundColor: tokens.colorPrimary,
    color: "white",
  },
  secondary: {
    backgroundColor: tokens.colorSecondary,
    color: "white",
  },
});

条件样式

复制代码
const messageStyles = stylex.create({
  base: {
    padding: 16,
    borderRadius: 4,
    marginBottom: 16,
  },
  success: {
    backgroundColor: "#d4edda",
    color: "#155724",
  },
  error: {
    backgroundColor: "#f8d7da",
    color: "#721c24",
  },
});

function Message({ type, children }) {
  const messageProps = stylex.props(
    messageStyles.base,
    type === "success" && messageStyles.success,
    type === "error" && messageStyles.error
  );

  return <div {...messageProps}>{children}</div>;
}

常见问题

Q: StyleX 与其他 CSS-in-JS 库有什么区别?

A: StyleX 的主要优势是零运行时开销,在构建时编译为静态 CSS。

Q: 如何处理动态样式?

A: 使用 CSS 变量或函数参数传递动态值。

Q: 是否支持 SSR?

A: 完全支持,由于样式在构建时生成,无客户端和服务端不一致问题。

总结

StyleX 是一个强大的零运行时 CSS-in-JS 解决方案,特别适合:

  • 大型 React 应用程序
  • 性能要求严格的项目
  • 需要类型安全的团队
  • 追求最佳构建产物的项目

主要优势:零运行时开销、类型安全、原子化 CSS、优秀的开发体验。通过构建时编译,StyleX 既保持了 CSS-in-JS 的开发体验,又获得了静态 CSS 的性能优势。

StyleX:Meta推出的高性能零运行时CSS-in-JS解决方案 - 高质量源码分享平台-免费下载各类网站源码与模板及前沿技术分享

相关推荐
Sane3 小时前
react函数组件怎么模拟类组件生命周期?一个 useEffect 搞定
前端·javascript·react.js
凉生阿新6 小时前
【React 插件】@uiw/react-md-editor 使用教程:从基础使用到自定义扩展
前端·react.js·前端框架
安心不心安6 小时前
React ahooks——副作用类hooks之useDebounceFn
前端·react.js·前端框架
Youyzq6 小时前
react 流式布局(图片宽高都不固定)的方案及思路
前端·react.js·前端框架
博客zhu虎康6 小时前
React18 严格模式下的双重渲染之谜
javascript·react.js·ecmascript
轻语呢喃7 小时前
Mock : 没有后端也能玩的虚拟数据
前端·javascript·react.js
薛定谔的算法8 小时前
React 项目骨架把“一万行灾难”拆成“百来个各司其职的小文件”
前端·react.js·前端框架
cainiao0806058 小时前
2025版React 20新特性深度解析:全栈革命的终极形态
前端·react.js·前端框架
这个昵称也不能用吗?10 小时前
react性能优化
javascript·react.js·性能优化