Next.js Emotion
Next.js Emotion[编辑 | 编辑源代码]
Next.js Emotion 是一种在 Next.js 框架中使用的 CSS-in-JS 样式解决方案,它结合了 Emotion 库的强大功能和 Next.js 的服务端渲染(SSR)及静态生成(SSG)能力。Emotion 提供了高性能的样式编写方式,支持动态样式、主题切换和组件化 CSS,同时保持优秀的开发体验。
介绍[编辑 | 编辑源代码]
Emotion 是一个流行的 CSS-in-JS 库,允许开发者直接在 JavaScript 或 TypeScript 中编写样式。在 Next.js 中集成 Emotion,可以充分利用其 SSR 和 SSG 优化能力,同时享受 Emotion 的灵活性和性能优势。
Emotion 的主要特点包括:
- 支持静态提取 CSS,减少运行时开销
- 提供 `css` prop 和 `styled` API 两种主要使用方式
- 支持嵌套选择器、伪类和媒体查询
- 内置自动厂商前缀和源映射支持
- 与 React 组件深度集成
安装与配置[编辑 | 编辑源代码]
要在 Next.js 项目中使用 Emotion,首先需要安装必要的依赖:
npm install @emotion/react @emotion/styled
# 或
yarn add @emotion/react @emotion/styled
对于 TypeScript 用户,还需要安装类型定义:
npm install --save-dev @types/emotion__react @types/emotion__styled
基本用法[编辑 | 编辑源代码]
Emotion 在 Next.js 中有两种主要使用方式:通过 `css` prop 和 `styled` API。
使用 css prop[编辑 | 编辑源代码]
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react'
function MyComponent() {
return (
<div
css={css`
background-color: hotpink;
&:hover {
color: white;
}
`}
>
This has a hotpink background.
</div>
)
}
使用 styled API[编辑 | 编辑源代码]
import styled from '@emotion/styled'
const Button = styled.button`
background: transparent;
border-radius: 3px;
border: 2px solid palevioletred;
color: palevioletred;
margin: 0.5em 1em;
padding: 0.25em 1em;
&:hover {
background-color: palevioletred;
color: white;
}
`
function MyComponent() {
return <Button>Styled Button</Button>
}
高级特性[编辑 | 编辑源代码]
主题支持[编辑 | 编辑源代码]
Emotion 提供了完整的主题支持,可以通过 `ThemeProvider` 在整个应用中共享主题变量:
import { ThemeProvider } from '@emotion/react'
const theme = {
colors: {
primary: 'hotpink',
secondary: 'blue'
}
}
function App() {
return (
<ThemeProvider theme={theme}>
<MyComponent />
</ThemeProvider>
)
}
在组件中使用主题:
import { useTheme } from '@emotion/react'
function ThemedComponent() {
const theme = useTheme()
return (
<div css={{ color: theme.colors.primary }}>
This text uses the primary color from theme
</div>
)
}
服务端渲染[编辑 | 编辑源代码]
Next.js 与 Emotion 的 SSR 集成需要额外配置。在 `_document.js` 中添加:
import Document, { Head, Html, Main, NextScript } from 'next/document'
import { extractCritical } from '@emotion/server'
export default class MyDocument extends Document {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx)
const styles = extractCritical(initialProps.html)
return {
...initialProps,
styles: (
<>
{initialProps.styles}
<style
data-emotion-css={styles.ids.join(' ')}
dangerouslySetInnerHTML={{ __html: styles.css }}
/>
</>
)
}
}
render() {
return (
<Html lang="en">
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
性能优化[编辑 | 编辑源代码]
Emotion 在 Next.js 中提供了多种性能优化选项:
1. 静态提取:通过 Babel 插件提取静态 CSS 2. 缓存:利用 Emotion 的缓存机制减少重复样式计算 3. 关键 CSS:使用 `extractCritical` 只发送渲染首屏所需样式
实际应用案例[编辑 | 编辑源代码]
以下是一个完整的 Next.js 页面组件示例,展示了 Emotion 的实际应用:
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react'
import styled from '@emotion/styled'
const Container = styled.div`
max-width: 1200px;
margin: 0 auto;
padding: 20px;
`
const Title = styled.h1`
color: ${props => props.theme.colors.primary};
text-align: center;
`
function HomePage() {
return (
<Container>
<Title>Welcome to Next.js with Emotion</Title>
<div css={css`
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
`}>
{[1, 2, 3].map(item => (
<div key={item} css={{
padding: '20px',
border: '1px solid #ddd',
borderRadius: '4px'
}}>
Card {item}
</div>
))}
</div>
</Container>
)
}
export default HomePage
与其他样式方案比较[编辑 | 编辑源代码]
特性 | Emotion | CSS Modules | Styled JSX | Tailwind CSS |
---|---|---|---|---|
SSR 支持 | ✔️ | ✔️ | ✔️ | ✔️ |
动态样式 | ✔️ | ❌ | 部分 | 部分 |
主题支持 | ✔️ | ❌ | ❌ | 通过配置 |
学习曲线 | 中等 | 低 | 低 | 中等 |
运行时大小 | 中等 | 无 | 小 | 大 |
最佳实践[编辑 | 编辑源代码]
1. 对于可重用组件,优先使用 `styled` API 2. 对于一次性样式,使用 `css` prop 3. 合理组织主题变量,避免硬编码颜色和尺寸 4. 利用 Emotion 的 `@emotion/babel-plugin` 进行编译时优化 5. 在大型项目中,考虑将样式与组件分离到单独文件中
常见问题[编辑 | 编辑源代码]
为什么需要 @jsxImportSource 注释?[编辑 | 编辑源代码]
这是为了告诉 Babel 使用 Emotion 的 JSX 转换而不是 React 的默认转换。在 Next.js 中,也可以通过修改 Babel 配置来全局设置。
如何禁用 Emotion 的开发样式标签?[编辑 | 编辑源代码]
在生产环境中,Emotion 会自动使用更高效的样式标签。如果需要手动控制,可以设置:
import { CacheProvider } from '@emotion/react'
import createCache from '@emotion/cache'
const cache = createCache({
key: 'my-prefix',
speedy: process.env.NODE_ENV === 'production'
})
function App() {
return (
<CacheProvider value={cache}>
{/* 你的应用 */}
</CacheProvider>
)
}
总结[编辑 | 编辑源代码]
Next.js Emotion 提供了强大而灵活的样式解决方案,特别适合需要动态样式、主题支持和 SSR 优化的项目。通过合理使用 Emotion 的各种特性,开发者可以创建高性能、可维护的样式系统,同时享受优秀的开发体验。