Stitches
以变体系统和类型推导著称的现代 CSS-in-JS 库
Stitches 曾以强大的 variants、设计令牌和类型体验受到关注,但项目已停止维护,新项目通常不再推荐采用。
Stitches
类型友好的 CSS-in-JS 库,提供近似零运行时、SSR、多变体支持和一流的开发者体验。
⚠️ 重要提示:Stitches 已于 2023 年 6 月停止维护,GitHub 仓库已于 2026 年 4 月 25 日正式归档(read-only)。请勿在新项目中使用。
技术简介说明
Stitches 是由 Modulz 团队(后被 WorkOS 收购)开发的一款 CSS-in-JS 样式解决方案。它的核心设计理念是在保持接近零运行时开销的前提下,提供强大的组件化样式能力。Stitches 通过将样式提取为原子化 CSS 类名来实现高性能,避免了传统 CSS-in-JS 库在运行时的重复计算开销。
Stitches 最大的特色是其强大的变体(Variants)系统,将变体视为一等公民,支持多变体组合、复合变体和响应式变体。配合完整的 TypeScript 类型推导、设计令牌(Design Tokens)系统和主题切换能力,Stitches 在 2021-2022 年间成为 React 生态中备受关注的现代样式方案。
然而,随着 React Server Components 的兴起和 React 生态对静态样式提取的强烈倾向,运行时 CSS-in-JS 方案面临根本性挑战。适配现代 React 架构需要对 Stitches 引擎进行彻底重构以支持静态提取,这需要大量工程投入。由于维护团队资源不足,项目于 2023 年 6 月停止活跃维护,GitHub 仓库于 2026 年 4 月正式归档。
基本信息
| 项目 | 详情 |
|---|---|
| 官网 | stitches.dev |
| GitHub | stitchesjs/stitches |
| License | MIT(Copyright © 2022-present WorkOS) |
| 最新版本 | v1.2.8(2022 年 4 月 25 日发布) |
| npm 包 | @stitches/core(框架无关)、@stitches/react(React 封装) |
| 原始维护者 | Pedro Duarte、Jonathan Neal、Abdulhadi Alhallak(Modulz → WorkOS) |
| GitHub Stars | ~7.8k |
| 语言构成 | JavaScript 89.8%、TypeScript 10.2% |
| 包体积 | @stitches/core ~5.9kb gzipped、@stitches/react ~6.1kb gzipped |
| 维护状态 | ⛔ 已停止维护(2023 年 6 月),仓库已归档(2026 年 4 月) |
| 周下载量 | ~174(截至 2025 年,相比 @emotion/react 的 ~19M 急剧萎缩) |
快速上手
安装
# React 项目
npm install @stitches/react
# 框架无关(Vue、Svelte、原生 HTML 等)
npm install @stitches/core基础配置
// stitches.config.ts
import { createStitches } from '@stitches/react'
export const {
styled,
css,
globalCss,
keyframes,
getCssText,
theme,
createTheme,
config,
} = createStitches({
// 主题前缀
prefix: '',
// 主题令牌(Design Tokens)
theme: {
colors: {
gray100: '#fcfcfc',
gray200: '#e8e8e8',
gray300: '#d6d6d6',
gray400: '#c4c4c4',
gray500: '#b2b2b2',
gray600: '#a0a0a0',
gray700: '#8e8e8e',
gray800: '#7c7c7c',
gray900: '#6a6a6a',
blue100: '#e6f0ff',
blue500: '#0066ff',
blue800: '#003d99',
violet100: '#f0e6ff',
violet500: '#7700ff',
violet800: '#4d0099',
// 语义化别名
primary: '$violet500',
secondary: '$blue500',
background: '$gray100',
text: '$gray900',
},
space: {
1: '4px',
2: '8px',
3: '12px',
4: '16px',
5: '24px',
6: '32px',
7: '48px',
8: '64px',
9: '80px',
},
fontSizes: {
xs: '12px',
sm: '14px',
base: '16px',
lg: '18px',
xl: '20px',
'2xl': '24px',
'3xl': '30px',
},
fonts: {
sans: 'system-ui, -apple-system, sans-serif',
mono: 'Menlo, monospace',
},
radii: {
sm: '4px',
md: '8px',
lg: '16px',
round: '9999px',
},
shadows: {
sm: '0 1px 2px rgba(0, 0, 0, 0.05)',
md: '0 4px 6px rgba(0, 0, 0, 0.1)',
lg: '0 10px 15px rgba(0, 0, 0, 0.15)',
},
},
// 响应式断点
media: {
bp1: '(min-width: 480px)',
bp2: '(min-width: 768px)',
bp3: '(min-width: 1024px)',
bp4: '(min-width: 1280px)',
},
// 自定义工具函数
utils: {
// 简写属性
pt: (value) => ({ paddingTop: value }),
pb: (value: string) => ({ paddingBottom: value }),
px: (value: string) => ({ paddingLeft: value, paddingRight: value }),
py: (value: string) => ({ paddingTop: value, paddingBottom: value }),
mx: (value: string) => ({ marginLeft: value, marginRight: value }),
my: (value: string) => ({ marginTop: value, marginBottom: value }),
// 复合工具
size: (value: string) => ({
width: value,
height: value,
}),
// 省略号
ellipsis: (value: boolean) =>
value === true
? {
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
}
: {},
},
})最小示例
// Button.tsx
import { styled } from './stitches.config'
const Button = styled('button', {
// 基础样式
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
borderRadius: '$md',
fontFamily: '$sans',
border: 'none',
cursor: 'pointer',
transition: 'all 150ms ease',
// 变体定义
variants: {
// 颜色变体
color: {
primary: {
backgroundColor: '$primary',
color: 'white',
'&:hover': { backgroundColor: '$violet800' },
},
secondary: {
backgroundColor: '$secondary',
color: 'white',
'&:hover': { backgroundColor: '$blue800' },
},
ghost: {
backgroundColor: 'transparent',
color: '$text',
'&:hover': { backgroundColor: '$gray200' },
},
},
// 尺寸变体
size: {
sm: { px: '$2', py: '$1', fontSize: '$sm' },
md: { px: '$4', py: '$2', fontSize: '$base' },
lg: { px: '$6', py: '$3', fontSize: '$lg' },
},
// 布尔变体
outlined: {
true: {
backgroundColor: 'transparent',
border: '2px solid currentColor',
},
},
},
// 默认变体值
defaultVariants: {
color: 'primary',
size: 'md',
},
// 复合变体
compoundVariants: [
{
color: 'primary',
outlined: true,
css: {
borderColor: '$primary',
color: '$primary',
},
},
{
color: 'secondary',
outlined: true,
css: {
borderColor: '$secondary',
color: '$secondary',
},
},
],
})
// 使用
function App() {
return (
<div style={{ display: 'flex', gap: '16px', padding: '32px' }}>
<Button>主要按钮</Button>
<Button color="secondary">次要按钮</Button>
<Button color="ghost">幽灵按钮</Button>
<Button outlined>轮廓按钮</Button>
<Button size="lg" color="primary">
大号按钮
</Button>
</div>
)
}核心概念与架构
整体架构
Stitches 的架构围绕 createStitches 函数展开,通过一份配置对象生成一整套样式 API:
createStitches(config)
├── styled() → 创建带样式的 React 组件
├── css() → 创建可复用的样式对象
├── globalCss() → 定义全局样式
├── keyframes() → 定义关键帧动画
├── getCssText() → 获取 SSR 用 CSS 文本
├── theme → 默认主题对象
├── createTheme() → 创建额外主题
└── config → 导出的配置引用
stitches.config.ts 配置结构
配置文件是 Stitches 的核心,定义了所有设计令牌、媒体查询和自定义工具函数:
import { createStitches } from '@stitches/react'
export const { styled, css, /* ... */ } = createStitches({
prefix: string, // CSS 变量前缀
theme: ThemeConfig, // 设计令牌定义
media: MediaConfig, // 响应式断点
utils: UtilsConfig, // 自定义工具函数
})Token 系统
Stitches 遵循 System UI Theme Specification,提供 14 种内置令牌类别:
| 类别 | 自动映射属性 | 示例 |
|---|---|---|
colors | color, background, borderColor 等 | $primary → $violet500 |
space | margin, padding, gap 等 | $4 → 16px |
fontSizes | font-size | $base → 16px |
fonts | font-family | $sans → system-ui, ... |
fontWeights | font-weight | $bold → 700 |
lineHeights | line-height | $normal → 1.5 |
letterSpacings | letter-spacing | $tight → -0.01em |
sizes | width, height | $container → 1200px |
borderWidths | border-width | $thin → 1px |
borderStyles | border-style | $solid → solid |
radii | border-radius | $md → 8px |
shadows | box-shadow | $sm → 0 1px 2px ... |
zIndices | z-index | $modal → 1000 |
transitions | transition | $fast → 150ms ease |
令牌使用规则:
// 前缀 $ 引用令牌
backgroundColor: '$primary'
// 语义化别名
colors: {
primary: '$violet500', // 引用同 scale 上的其他值
}
// 局部作用域令牌(双 $$)
css: {
$$shadowColor: 'rgba(0,0,0,0.1)',
boxShadow: '0 2px 4px $$shadowColor',
}
// Scale 前缀跨类别引用
color: '$colors$purple500'Variants 变体系统
变体是 Stitches 最核心的特性,将组件的样式变化抽象为声明式配置:
const Card = styled('div', {
variants: {
// 单选变体
variant: {
elevated: { boxShadow: '$md' },
outlined: { border: '1px solid $gray300' },
ghost: { backgroundColor: 'transparent' },
},
// 尺寸变体
size: {
sm: { padding: '$2' },
md: { padding: '$4' },
lg: { padding: '$6' },
},
// 布尔变体
interactive: {
true: {
cursor: 'pointer',
transition: 'transform 150ms ease',
'&:hover': { transform: 'translateY(-2px)' },
},
},
},
defaultVariants: {
variant: 'elevated',
size: 'md',
},
// 复合变体:多个变体条件同时满足时生效
compoundVariants: [
{
variant: 'elevated',
interactive: true,
css: {
boxShadow: '$lg',
'&:hover': { boxShadow: '$lg', transform: 'translateY(-4px)' },
},
},
],
})
// 使用
<Card variant="elevated" size="lg" interactive={true} />响应式变体
配合 media 配置,变体可以直接声明响应式行为:
<Card
size={{
'@initial': 'sm', // 默认(最小屏幕)
'@bp1': 'md', // 480px+
'@bp2': 'lg', // 768px+
}}
/>核心特性
1. 近似零运行时
Stitches 通过跳过冗余的 prop 插值计算,将运行时开销降到最低。核心包仅 ~5.9kb(gzipped),不会在运行时解析和注入所有样式,而是按需生成原子化 CSS 类名。
2. 强大的变体系统
变体是 Stitches 的一等公民。支持单选变体、布尔变体、复合变体(compound variants)、默认变体(default variants)和响应式变体,覆盖了组件样式变化的所有场景。类型系统自动推导变体 prop 的类型。
3. 设计令牌(Design Tokens)
遵循 System UI Theme Specification,提供 14 种令牌类别,自动映射到对应的 CSS 属性。支持语义化别名和局部作用域令牌,让设计系统与代码紧密绑定。
4. 完整的 TypeScript 支持
API 完全类型化,styled() 创建的组件自动推导变体 prop 类型,CSS 和 VariantProps 类型工具允许在任意位置获取精确类型。无需额外配置即可获得完整的编辑器智能提示。
import { CSS, VariantProps } from '@stitches/react'
// CSS 类型用于 css prop
type ButtonCSS = CSS
// 提取组件的变体类型
type ButtonVariants = VariantProps<typeof Button>5. 主题切换
基于 CSS 变量实现主题系统,createTheme() 创建的主题切换只需切换 className,无需重新渲染组件树:
const darkTheme = createTheme({
colors: {
background: '#1a1a1a',
text: '#ffffff',
primary: '#a78bfa',
},
})
// 应用主题
document.documentElement.classList.add(darkTheme.className)6. 服务端渲染(SSR)
内置 SSR 支持,getCssText() 可以获取所有已注入样式的 CSS 文本,确保服务端和客户端的样式一致,包括响应式元素的主题样式:
// Next.js _document.tsx
import { getCssText } from './stitches.config'
export default class MyDocument extends Document {
render() {
return (
<Html>
<Head>
<style
id="stitches"
dangerouslySetInnerHTML={{ __html: getCssText() }}
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}7. 自定义工具函数
通过 utils 配置定义语义化的样式简写,让样式代码更简洁、更具表达力:
utils: {
// 简写
pt: (value) => ({ paddingTop: value }),
px: (value) => ({ paddingLeft: value, paddingRight: value }),
// 复合工具
size: (value) => ({ width: value, height: value }),
// 条件工具
truncate: (lines: number) => ({
overflow: 'hidden',
textOverflow: 'ellipsis',
display: '-webkit-box',
WebkitLineClamp: lines,
WebkitBoxOrient: 'vertical',
}),
}8. css prop 样式覆盖
css 属性允许在组件实例上进行一次性样式覆盖,类型安全且与变体系统协同工作:
<Button
css={{
backgroundColor: '$blue500',
borderRadius: '$round',
'@bp2': {
padding: '$6',
},
}}
/>9. 组件组合(Composition)
Stitches 支持通过 styled() 包装已有组件来继承和扩展样式,保持变体的传递性:
// 基础组件
const BaseButton = styled('button', { /* ... */ })
// 继承并扩展
const IconButton = styled(BaseButton, {
size: '$8',
borderRadius: '$round',
padding: 0,
})10. 关键路径 CSS
Stitches 只注入实际使用到的样式,生成的 CSS 遵循关键路径原则,减少首屏加载的样式体积。
生态图
┌─────────────────────────────────────────────────────────┐
│ Stitches 生态 │
├─────────────────────────────────────────────────────────┤
│ │
│ 核心包 │
│ ├── @stitches/react → React 集成(styled, css prop) │
│ └── @stitches/core → 框架无关核心 API │
│ │
│ 社区扩展 │
│ ├── stitches-native → React Native 适配(社区) │
│ ├── stitches-view → Vue 适配(实验性) │
│ ├── stitches-svelte → Svelte 适配(实验性) │
│ └── @stitches/styled → styled-components 风格 API │
│ │
│ 工具集成 │
│ ├── stitches-props → 变体 prop 过滤工具 │
│ ├── stitches-token-extract → 令牌提取工具 │
│ └── Figma Tokens 插件 → 设计稿 → Stitches 令牌同步 │
│ │
│ 迁移工具 │
│ ├── Stylify 迁移指南 → Stitches → Stylify 迁移路径 │
│ └── 社区迁移脚本 → Stitches → Tailwind 转换 │
│ │
└─────────────────────────────────────────────────────────┘
适用场景
⚠️ 以下场景描述基于 Stitches 活跃维护时期的能力。由于项目已停止维护,生产环境不建议继续使用。
1. 组件库开发
Stitches 的变体系统天然适合构建组件库。通过声明式变体定义,组件库可以轻松暴露丰富的样式配置接口,同时保持类型安全。Radix UI 的早期版本就使用了 Stitches。
2. 设计系统集成
14 种令牌类别 + 语义化别名 + 主题切换,使 Stitches 适合构建与 Figma 设计稿同步的设计系统。
3. 需要多变体组件的应用
按钮、徽章、卡片、输入框等组件的样式变化(颜色、尺寸、状态),通过变体声明式管理,比条件类名更清晰。
4. SSR 应用
内置 SSR 支持使 Stitches 适合 Next.js 等 SSR 框架,getCssText() 提供开箱即用的服务端样式注入。
5. 性能敏感的应用
~6kb 的包体积和原子化 CSS 生成,适合对包体积和运行时性能有严格要求的场景。
6. 需要主题切换的应用
基于 CSS 变量的主题系统,支持暗色模式、品牌主题等运行时主题切换,无需重新渲染组件树。
7. 跨框架项目
@stitches/core 提供框架无关的 API,可在 Vue、Svelte、Web Components 等任何框架中使用。
开发与工程化
项目结构建议
src/
├── stitches/
│ ├── config.ts # createStitches 配置
│ ├── tokens/
│ │ ├── colors.ts # 颜色令牌
│ │ ├── space.ts # 间距令牌
│ │ └── typography.ts # 字体令牌
│ ├── themes/
│ │ ├── dark.ts # 暗色主题
│ │ └── brand.ts # 品牌主题
│ ├── utils.ts # 自定义工具函数
│ └── global.ts # 全局样式
├── components/
│ ├── Button/
│ │ ├── Button.tsx # 组件定义
│ │ └── Button.stories.tsx
│ └── Card/
│ └── Card.tsx
└── pages/
└── _document.tsx # SSR 样式注入
TypeScript 配置
{
"compilerOptions": {
"strict": true,
"jsx": "react-jsx"
}
}Stitches 无需额外的 TypeScript 插件,类型推导开箱即用。
与 Next.js 集成
// next.config.js
// Stitches 无需特殊 webpack 配置
module.exports = {
reactStrictMode: true,
}
// pages/_document.tsx
import Document, { Html, Head, Main, NextScript } from 'next/document'
import { getCssText } from '../stitches/config'
export default class MyDocument extends Document {
render() {
return (
<Html>
<Head>
<style
id="stitches"
dangerouslySetInnerHTML={{ __html: getCssText() }}
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}与测试工具集成
// jest.setup.ts
// Stitches 组件在测试环境中可直接使用,无需额外 mock
import '@testing-library/jest-dom'
// vitest 同样兼容
// Stitches 生成的类名在 jsdom 中正常工作性能与安全
性能特征
| 指标 | 数值 | 说明 |
|---|---|---|
| 包体积(core) | ~5.9kb gzipped | 框架无关核心 |
| 包体积(react) | ~6.1kb gzipped | React 集成 |
| 运行时开销 | 近似零 | 跳过冗余 prop 插值 |
| CSS 生成 | 原子化 | 只注入使用到的样式 |
| 首屏加载 | 关键路径 CSS | 自动去重、按需生成 |
| 主题切换 | className 切换 | 无组件树重渲染 |
性能优化策略
- 合理使用变体:避免创建过多变体组合导致 CSS 膨胀
- 令牌复用:尽量使用设计令牌而非硬编码值,减少 CSS 规则数量
- 组件组合:通过
styled()组合代替嵌套的 css prop - SSR 预渲染:使用
getCssText()避免客户端闪烁
安全注意事项
- Stitches 不涉及用户输入的 HTML 注入,样式值由开发者控制
dangerouslySetInnerHTML用于 SSR 样式注入是安全的(内容由 Stitches 生成)- 避免将用户输入直接作为样式值传入,防止 CSS 注入风险
- 项目已停止维护,不再接收安全补丁,生产环境存在安全风险
技术对比
CSS-in-JS 方案对比
| 特性 | Stitches | Emotion | styled-components | Vanilla Extract | Tailwind CSS | Panda CSS |
|---|---|---|---|---|---|---|
| 维护状态 | ⛔ 已归档 | ✅ 活跃 | ⚠️ 维护模式 | ✅ 活跃 | ✅ 活跃 | ✅ 活跃 |
| 运行时 | 近似零 | 运行时 | 运行时 | 零(构建时) | 零(构建时) | 零(构建时) |
| 包体积 | ~6kb | ~10kb | ~12kb | 零运行时 | 零运行时 | 零运行时 |
| TypeScript | ✅ 完整推导 | ✅ 支持 | ✅ 支持 | ✅ 完整推导 | ✅ 支持 | ✅ 完整推导 |
| 变体系统 | ✅ 一等公民 | ⚠️ 需手动实现 | ⚠️ 需手动实现 | ❌ 无内置 | ❌ 无内置 | ✅ 内置 |
| 设计令牌 | ✅ 14 种类别 | ⚠️ 需手动 | ⚠️ 需手动 | ✅ 完整支持 | ⚠️ 需配置 | ✅ 完整支持 |
| 主题切换 | ✅ className | ✅ ThemeProvider | ✅ ThemeProvider | ✅ 构建时 | ✅ 配置文件 | ✅ 主题配置 |
| SSR | ✅ getCssText | ✅ 支持 | ✅ 支持 | ✅ 构建时输出 | ✅ 静态提取 | ✅ 构建时输出 |
| RSC 兼容 | ❌ 不兼容 | ⚠️ 需特殊处理 | ⚠️ 需特殊处理 | ✅ 完全兼容 | ✅ 完全兼容 | ✅ 完全兼容 |
| 框架支持 | React / 通用 | React / 通用 | React | 任意框架 | 任意框架 | 任意框架 |
| 社区活跃度 | ~174/周下载 | ~19M/周下载 | ~7M/周下载 | 增长中 | 极高 | 增长中 |
与同类方案深度对比
vs Emotion:
Stitches 的变体系统和令牌系统更成熟,开发体验更好;Emotion 生态更大、社区更活跃、维护更稳定。Stitches 的原子化输出更高效,Emotion 的 css prop 更灵活。
vs styled-components: 两者 API 风格相似,但 Stitches 有内置变体和令牌系统。styled-components 历史更长但已于 2025 年进入维护模式。
vs Vanilla Extract: Vanilla Extract 是零运行时方案,与 React Server Components 完全兼容。Stitches 是运行时方案,与 RSC 不兼容。这是两者在 2024-2026 年的根本性差异。
vs Tailwind CSS: Tailwind 是 utility-first 方案,生态和工具链远更成熟。Stitches 的组件化方式更接近 React 思维模型,但 Tailwind 的社区和生态在 2026 年已形成压倒性优势。
vs Panda CSS: Panda CSS 兼具零运行时和类 CSS-in-JS 的开发体验(包括变体系统),可以看作是 Stitches 理念在现代架构下的继承者。
最佳实践
1. 令牌优先原则
始终使用设计令牌而非硬编码值,确保设计系统的一致性:
// ✅ 推荐:使用令牌
const Card = styled('div', {
backgroundColor: '$background',
borderRadius: '$md',
padding: '$4',
boxShadow: '$sm',
})
// ❌ 不推荐:硬编码
const Card = styled('div', {
backgroundColor: '#fcfcfc',
borderRadius: '8px',
padding: '16px',
boxShadow: '0 1px 2px rgba(0,0,0,0.05)',
})2. 变体粒度控制
变体应该覆盖组件的主要样式变化,但不宜过细:
// ✅ 推荐:合理粒度
const Button = styled('button', {
variants: {
color: { primary: {}, secondary: {}, ghost: {} },
size: { sm: {}, md: {}, lg: {} },
},
})
// ❌ 不推荐:过细粒度(用 css prop 代替)
const Button = styled('button', {
variants: {
marginTop: { '4px': {}, '8px': {}, '12px': {} }, // 应使用 css prop
},
})3. 复合变体谨慎使用
复合变体强大但容易导致样式冲突,建议只在必要时使用:
// ✅ 推荐:只在真正需要时使用
compoundVariants: [
{
color: 'primary',
disabled: true,
css: { opacity: 0.5, cursor: 'not-allowed' },
},
]4. 工具函数复用
将常用的 CSS 组合抽象为工具函数,提高代码一致性:
utils: {
// 文本截断
truncate: (lines: number) => ({
overflow: 'hidden',
textOverflow: 'ellipsis',
display: '-webkit-box',
WebkitLineClamp: lines,
WebkitBoxOrient: 'vertical',
}),
// Flex 居中
center: () => ({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}),
}5. 主题分离
将令牌定义、主题定义和组件定义分离,便于维护:
// tokens/colors.ts
export const lightColors = { /* ... */ }
export const darkColors = { /* ... */ }
// themes/dark.ts
import { createTheme } from '../config'
export const darkTheme = createTheme({ colors: darkColors })
// components/Button.tsx
import { styled } from '../config'
// 组件只引用令牌名,不关心具体值6. 组件组合优于样式覆盖
优先通过 styled() 组合创建新组件,而非大量使用 css prop:
// ✅ 推荐:组件组合
const PrimaryButton = styled(Button, {
color: 'primary',
size: 'md',
})
// ⚠️ 可以但应避免过度使用:css prop 覆盖
<Button color="primary" size="md" css={{ marginTop: '$4' }} />7. SSR 样式注入
确保正确配置 SSR,避免客户端闪烁(FOUC):
// Next.js: 在 _document.tsx 中注入 getCssText()
// Remix: 在 root.tsx 的 Links 中注入
// 其他 SSR 框架: 在 <head> 中注入 <style> 标签技术局限与边界
⛔ 项目已停止维护
这是当前最大的局限。 Stitches 于 2023 年 6 月停止活跃维护,GitHub 仓库于 2026 年 4 月 25 日正式归档为 read-only。这意味着:
- 不会有任何 bug 修复
- 不会有任何安全补丁
- 不会有任何新功能开发
- 不会有 React 新版本适配(特别是 React Server Components)
- 不会有 Next.js App Router 适配
根本性技术限制
-
不兼容 React Server Components:Stitches 是运行时 CSS-in-JS 方案,依赖客户端 JavaScript 执行来生成和注入样式。RSC 要求样式在构建时静态提取,Stitches 的架构无法支持这一点,要适配需要对引擎进行彻底重写。
-
不兼容 Next.js App Router:App Router 的组件默认为 Server Components,Stitches 的
styled()需要客户端上下文才能工作。虽然可以通过'use client'强制客户端渲染,但这违背了 RSC 的性能优势。 -
静态提取不可行:社区曾讨论通过 Babel 插件实现静态提取(Issue #955),但由于需要将运行时引擎的完整逻辑复制到编译时,复杂度极高,WorkOS 收购后未投入资源实现。
-
社区接管失败:维护者曾试图将项目开放给社区领导(Discussion #1149),虽有开发者表示愿意贡献,但最终未能形成有效的维护团队。
版本停滞
- 最后一个版本 v1.2.8 发布于 2022 年 4 月,至今已超 4 年
- Stitches 从未发布 2.0 版本,也没有 2.0 的开发计划
- npm 周下载量从高峰期降至约 174 次/周
迁移必要性
对于仍在使用 Stitches 的项目,建议尽快规划迁移。可选方案:
| 迁移目标 | 迁移难度 | 适合场景 |
|---|---|---|
| Panda CSS | 中等 | 最接近 Stitches 的开发体验,有变体系统 |
| Vanilla Extract | 较高 | 零运行时、类型安全、RSC 兼容 |
| Tailwind CSS | 较高 | 生态最大、工具链最成熟 |
| CSS Modules | 中等 | 简单直接、框架无关 |
| Styled Components | 低 | API 风格接近,但自身也进入维护模式 |
学习资源
官方资源
- Stitches 官方文档 — 完整的 API 文档和指南(已停止更新)
- Stitches 官方博客 — 版本发布公告
- Stitches GitHub — 源码和 Issues(已归档)
- GitHub Discussion #1149 — 关于 Stitches 未来的讨论
教程与文章
- Stitches Crash Course (YouTube) — 视频教程
- Stitches CSS - Is It Any Good? (DEV Community) — 使用体验分享
- Angular + Stitches (Sandro Roth) — Angular 集成指南
- React Native Stitches — React Native 适配
迁移资源
- Stitches → Stylify 迁移指南 — 官方迁移对照
- State of CSS-in-JS 2026 (OpenReplay) — 2026 年 CSS-in-JS 现状分析
- State of CSS-in-JS 2026 (PkgPulse) — 行业趋势报告
2026 年现状
项目状态总结
| 维度 | 2021-2022(活跃期) | 2023(停止维护) | 2026(当前) |
|---|---|---|---|
| 维护状态 | 活跃开发 | 停止维护 | 仓库已归档 |
| 版本 | v1.x 持续迭代 | v1.2.8 最终版 | 无更新 |
| 周下载量 | 数万级 | 下降中 | ~174/周 |
| 社区 | Discord 活跃、Radix UI 采用 | 社区失望 | 基本无人使用 |
| 生态兼容 | 全框架兼容 | RSC 不兼容暴露 | 与现代 React 架构脱节 |
CSS-in-JS 生态变迁
Stitches 的衰落是 CSS-in-JS 生态整体变迁的缩影:
- 2023 年:React 团队明确推荐静态 CSS 方案,运行库 CSS-in-JS 开始受到质疑
- 2023 年 6 月:Stitches 宣布停止维护
- 2024 年:Next.js App Router 成为主流,Server Components 普及,运行时 CSS-in-JS 兼容性问题加剧
- 2025 年初:styled-components 进入维护模式,CSS-in-JS 领域标志性事件
- 2025-2026 年:零运行时方案(Vanilla Extract、Panda CSS、StyleX)和 utility-first 方案(Tailwind CSS)成为主流选择
- 2026 年 4 月:Stitches GitHub 仓库正式归档
替代方案建议
对于不同场景的推荐替代方案:
| 需求 | 推荐方案 | 理由 |
|---|---|---|
| 最接近 Stitches 开发体验 | Panda CSS | 有变体系统、零运行时、RSC 兼容 |
| 最强类型安全 | Vanilla Extract | 构建时生成、完整类型推导 |
| 最大生态和社区 | Tailwind CSS | 工具链成熟、社区庞大、IDE 支持好 |
| 简单迁移路径 | CSS Modules | 概念简单、框架无关、零配置 |
| React Server Components 项目 | Vanilla Extract / Panda CSS | 零运行时、完全兼容 RSC |
| 组件库开发 | Panda CSS / Vanilla Extract | 变体支持 + 零运行时 |
结论
Stitches 是一个在特定时期解决了正确问题的优秀项目——它在变体系统、设计令牌和开发者体验方面树立了标杆。然而,前端架构的演进(特别是 React Server Components 的普及)使得运行时 CSS-in-JS 方案面临根本性挑战。对于新项目,强烈建议选择零运行时替代方案。对于仍在运行 Stitches 的存量项目,建议尽快制定迁移计划。
📅 文档更新时间:2026 年 7 月
📌 数据来源:stitches.dev、GitHub、npm、Best of JS、PkgPulse、OpenReplay、社区讨论