簡介
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解決方案 - 高質量源碼分享平臺-免費下載各類網站源碼與模板及前沿技術分享