如何在React移动端项目引入UnoCSS及实现热更新

140 阅读3分钟

UnoCSS 是一个即时按需生成的原子化 CSS 引擎,它凭借独特的理念和设计,在前端开发中迅速流行。对于我们小型的项目能实现快速开发和优化打包体积,非常nice!

但在看官方文档的时候发现,按照文档操作并不能顺利的引入,或者引入之后没办法热更新,研究了大半天解决了这个问题。下面我们来一步一步的把unocss引入我们的项目吧~

目录结构

首先看一下项目结构: 我的项目本身是用React, TypeScript, 和Ant Design

  src
  ├── components/     # Reusable components
  ├── pages/         # Page components
  ├── store/         # Redux store configuration
  ├── utils/         # Utility functions
  ├── services/      # API services
  ├── constants/     # Constants and configuration
  ├── subpackages/   # Subpackage modules
  ├── uno.css
  └── index.tsx
  craco.config.js
  tsconfig.json
  uno.config.ts
  package.json

依赖包

然后看下package.json(省略掉非unocss部分)

{
  "name": "pos_ipad",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    ...
  },
  "scripts": {
    "start": "yarn uno:generate && cross-env NODE_ENV=development craco start",
    "build": "yarn uno:generate && cross-env NODE_ENV=production craco build"
    "uno:generate": "unocss \"src/**/*.{js,jsx,ts,tsx}\" -o src/uno.css",
    "uno:watch": "unocss \"src/**/*.{js,jsx,ts,tsx}\" -o src/uno.css --watch",
    "dev": "concurrently \"yarn start\" \"yarn uno:watch\""
  },
  "eslintConfig": {
  	...
  },
  "browserslist": {
  	...
  },
  "devDependencies": {
    "@unocss/postcss": "^66.3.2",
    "@unocss/preset-attributify": "^66.3.2",
    "@unocss/preset-icons": "^66.3.2",
    "@unocss/preset-rem-to-px": "^66.3.2",
    "@unocss/preset-uno": "^66.3.2",
    "@unocss/transformer-directives": "^66.3.2",
    "@unocss/transformer-variant-group": "^66.3.2",
    "@unocss/webpack": "^66.3.2",
    "concurrently": "^9.2.0",
    "unocss": "^66.3.2"
    ...
  },
}

按照devDependencies安装列表,就可以把用到的uno相关npm包安装好,接下来配置script。 我们想执行在运行项目的同时watch样式改动,还需要安装一个concurrently,参考scriptdev的配置。

unocss配置及引用

那么到现在为止我们的依赖和启动脚本都配置好啦,接下来看unocss配置部分。 craco.config.js

const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
module.exports = {
  webpack: {
    configure: (webpackConfig) => {
      webpackConfig.resolve.plugins = [
        ...(webpackConfig.resolve.plugins || []),
        new TsconfigPathsPlugin({})
      ];
      return webpackConfig;
    },
  },
  //可以只参考这个引入
  style: {
    postcss: {
      plugins: [
        require('@unocss/postcss')(),
      ],
    },
  },
};

uno.config.ts 重中之重 可以根据自己项目情况调整配置,由于我要用px,所以多引入了一个presetRemToPx的npm,不用的话可以删掉

import { defineConfig, presetAttributify, presetIcons, transformerDirectives, transformerVariantGroup } from "unocss";
import { presetMini } from "@unocss/preset-mini";
import presetRemToPx from "@unocss/preset-rem-to-px";

export default defineConfig({
  // 扫描文件 - 在 webpack 模式下,这个配置会被 webpack 插件自动处理
  content: {
    filesystem: ["src/**/*.{js,jsx,ts,tsx}", "public/index.html"],
  },

  // 输出配置
  outputToCssLayers: false,

  // 预设
  presets: [
    presetMini(), // 默认预设,包含 Tailwind CSS 兼容的工具类
    presetAttributify(), // 属性化模式
    presetIcons({
      // 图标预设配置
      scale: 1.2,
      warn: true,
      collections: {
        // 可以添加你需要的图标集
        // carbon: () => import('@iconify-json/carbon/icons.json').then(i => i.default),
        // mdi: () => import('@iconify-json/mdi/icons.json').then(i => i.default),
      },
    }),
    presetRemToPx(), // rem 转 px 预设
  ],

  // 转换器
  transformers: [
    transformerDirectives(), // 支持 @apply 指令
    transformerVariantGroup(), // 支持变体组语法
  ],

  // 自定义规则
  rules: [],

  // 快捷方式
  shortcuts: [
    // 按钮样式
    ['btn', 'px-4 py-2 rounded inline-block cursor-pointer transition-colors duration-200 disabled:cursor-default disabled:opacity-50'],
    ['btn-primary', 'btn bg-blue-500 text-white hover:bg-blue-600 disabled:bg-gray-400'],
    ['btn-secondary', 'btn bg-gray-200 text-gray-800 hover:bg-gray-300 disabled:bg-gray-100'],

    // 卡片样式
    ['card', 'bg-white p-6 rounded-lg shadow-sm border border-gray-200'],
    ['card-hover', 'card hover:shadow-md transition-shadow duration-200'],

    // 布局快捷方式
    ['flex-center', 'flex items-center justify-center'],
    ['flex-col-center', 'flex flex-col items-center justify-center'],
  ],

  // 主题配置
  theme: {
    colors: {
      // 自定义颜色
      primary: "#1890ff",
      success: "#52c41a",
      warning: "#faad14",
      error: "#f5222d",
    },
    breakpoints: {
      // 响应式断点
      sm: "640px",
      md: "768px",
      lg: "1024px",
      xl: "1280px",
      "2xl": "1536px",
    },
  },

  // 安全列表 - 确保这些类不会被清除
  safelist: [
    // 'text-red-500',
    // 'bg-blue-500',
  ],
});

src/index.tsx 在入口文件中引入uno.css

import React from 'react';
import ReactDOM from 'react-dom/client';
import './uno.css';//重点只有这一行
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);
reportWebVitals();

验证

好啦,到现在为止我们的引入工作就结束啦,这个时候可以运行项目试一下啦,验证的方法是:如果新增了unocss的使用,在src/uno.css则会新增对应的css样式,由于我们做了热更新,所以src/uno.css文件会随着改动慢慢增多,注意:这个文件是不要手动更新的哦!(* ̄︶ ̄) 让我们启动项目试一下吧~ 在这里插入图片描述

看到UnoCSS的watch打印就说明项目启动成功啦~撒花!!!