Rust CSS-in-JS 转换库 swc_emotion 的使用,高效处理 Emotion 样式到 CSS 的编译转换
Rust CSS-in-JS 转换库 swc_emotion 的使用,高效处理 Emotion 样式到 CSS 的编译转换
安装
在项目目录中运行以下 Cargo 命令:
cargo add swc_emotion
或者在你的 Cargo.toml 中添加以下行:
swc_emotion = "0.97.0"
使用示例
以下是使用 swc_emotion 将 Emotion 样式转换为 CSS 的完整示例:
use swc_emotion::{transform, Config};
use swc_common::{SourceMap, FileName};
use std::sync::Arc;
fn main() {
// 创建源映射
let cm = Arc::new(SourceMap::default());
// 配置 swc_emotion
let config = Config {
// 可根据需要配置其他选项
..Default::default()
};
// 要转换的 Emotion 样式代码
let emotion_code = r#"
import { css } from '@emotion/react';
const styles = css`
color: hotpink;
&:hover {
color: rebeccapurple;
}
`;
"#;
// 创建输入文件
let fm = cm.new_source_file(
FileName::Custom("input.js".into()),
emotion_code.to_string()
);
// 执行转换
let output = transform(&fm, None, config).unwrap();
// 输出转换后的 CSS
println!("转换结果:\n{}", output.code);
}
示例输出
上述代码会将 Emotion 样式转换为纯 CSS,输出类似:
.css-1a2b3c4d {
color: hotpink;
}
.css-1a2b3c4d:hover {
color: rebeccapurple;
}
配置选项
swc_emotion 提供了一些配置选项:
let config = Config {
source_map: true, // 是否生成 source map
auto_label: true, // 是否自动添加标签
label_format: "[local]", // 标签格式
..Default::default()
};
完整示例代码
下面是一个更完整的示例,展示了如何处理多个 Emotion 样式并输出到文件:
use swc_emotion::{transform, Config};
use swc_common::{SourceMap, FileName};
use std::sync::Arc;
use std::fs::File;
use std::io::Write;
fn main() {
// 创建源映射
let cm = Arc::new(SourceMap::default());
// 配置 swc_emotion
let config = Config {
auto_label: true,
label_format: "[dirname]-[filename]-[local]",
..Default::default()
};
// 要转换的 Emotion 样式代码
let emotion_code = r#"
import { css, keyframes } from '@emotion/react';
const fadeIn = keyframes`
from { opacity: 0; }
to { opacity: 1; }
`;
const container = css`
animation: ${fadeIn} 0.5s ease-in;
padding: 16px;
& > button {
background: #f0f0f0;
border: 1px solid #ccc;
}
`;
"#;
// 创建输入文件
let fm = cm.new_source_file(
FileName::Custom("app.js".into()),
emotion_code.to_string()
);
// 执行转换
let output = transform(&fm, None, config).unwrap();
// 输出转换后的 CSS 到控制台
println!("转换结果:\n{}", output.code);
// 写入到 CSS 文件
let mut file = File::create("styles.css").unwrap();
file.write_all(output.code.as_bytes()).unwrap();
println!("CSS 已写入到 styles.css 文件");
}
完整示例输出
上述完整示例会输出类似以下 CSS 内容:
@keyframes app-js-fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.app-js-container {
animation: app-js-fadeIn 0.5s ease-in;
padding: 16px;
}
.app-js-container > button {
background: #f0f0f0;
border: 1px solid #ccc;
}
1 回复
Rust CSS-in-JS 转换库 swc_emotion 使用指南
完整示例demo
基本使用示例(来自原内容)
import { css } from '@emotion/react';
const styles = css`
color: hotpink;
&:hover {
color: rebeccapurple;
}
`;
function MyComponent() {
return <div css={styles}>Hello with Emotion!</div>;
}
styled组件示例(来自原内容)
import styled from '@emotion/styled';
const Button = styled.button`
background: ${props => props.primary ? 'hotpink' : 'white'};
color: ${props => props.primary ? 'white' : 'hotpink'};
font-size: 1rem;
padding: 0.5rem 1rem;
border: 2px solid hotpink;
border-radius: 3px;
`;
function MyComponent() {
return (
<div>
<Button>Normal</Button>
<Button primary>Primary</Button>
</div>
);
}
完整项目示例
// 项目入口文件 index.jsx
import React from 'react';
import ReactDOM from 'react-dom';
import { css } from '@emotion/react';
import styled from '@emotion/styled';
// 基本css使用示例
const containerStyle = css`
padding: 2rem;
background: #f5f5f5;
text-align: center;
`;
// 带props的styled组件
const DynamicButton = styled.button`
background: ${props => props.variant === 'primary' ? '#ff4081' : '#fff'};
color: ${props => props.variant === 'primary' ? '#fff' : '#ff4081'};
border: 2px solid #ff4081;
border-radius: 4px;
padding: 8px 16px;
font-size: 14px;
cursor: pointer;
margin: 0 8px;
transition: all 0.2s;
&:hover {
opacity: 0.8;
}
`;
// 组合样式
const dangerStyle = css`
color: #d32f2f;
font-weight: bold;
`;
function App() {
return (
<div css={containerStyle}>
<h1>swc_emotion 示例应用</h1>
<div css={{ margin: '20px 0' }}>
<DynamicButton>默认按钮</DynamicButton>
<DynamicButton variant="primary">主要按钮</DynamicButton>
</div>
<p css={dangerStyle}>这是一个警告文本</p>
{/* 样式组合 */}
<p css={[dangerStyle, { fontSize: '1.2rem' }]}>
组合样式的警告文本
</p>
</div>
);
}
ReactDOM.render(<App />, document.getElementById('root'));
对应SWC配置
// .swcrc 配置文件
{
"jsc": {
"parser": {
"syntax": "ecmascript",
"jsx": true
},
"transform": {
"react": {
"runtime": "automatic"
}
},
"experimental": {
"plugins": [
["swc_emotion", {
"sourceMap": true,
"autoLabel": "dev-only",
"labelFormat": "[local]-[filename]"
}]
]
}
}
}
webpack集成配置
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'swc-loader',
options: {
jsc: {
parser: {
syntax: "ecmascript",
jsx: true
},
experimental: {
plugins: [
["swc_emotion", {
autoLabel: true,
labelFormat: "[local]"
}]
]
}
}
}
}
}
]
}
};
使用说明
- 安装必要依赖:
npm install @emotion/react @emotion/styled @swc/core swc_emotion swc-loader
- 确保项目结构包含:
my-project/
├── src/
│ ├── index.jsx # 入口文件
├── .swcrc # SWC配置文件
├── webpack.config.js # webpack配置
└── package.json
- 关键点说明:
swc_emotion
会自动处理所有css
和styled
模板字符串- 开发模式下建议启用
autoLabel
方便调试 - 生产环境可关闭
sourceMap
以减少体积