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]"
                  }]
                ]
              }
            }
          }
        }
      }
    ]
  }
};

使用说明

  1. 安装必要依赖:
npm install @emotion/react @emotion/styled @swc/core swc_emotion swc-loader
  1. 确保项目结构包含:
my-project/
├── src/
│   ├── index.jsx    # 入口文件
├── .swcrc           # SWC配置文件
├── webpack.config.js # webpack配置
└── package.json
  1. 关键点说明:
  • swc_emotion会自动处理所有cssstyled模板字符串
  • 开发模式下建议启用autoLabel方便调试
  • 生产环境可关闭sourceMap以减少体积
回到顶部