UnoCSS 集成与使用(替代 SCSS)
本节说明如何将 UnoCSS 集成进基于本框架的 Angular 项目,并作为 SCSS 的补充或替代 使用,以原子化工具类提升样式开发效率。
1. 为何用 UnoCSS 替代/补充 SCSS
- 原子化 CSS:按需生成工具类(如
flex、p-4、text-blue-500),减少手写 CSS/SCSS 体积与重复。 - 与组件共存:可在模板中直接写类名,也可在
styles或全局样式中使用;与现有 SCSS 文件可逐步迁移、并存。 - 构建集成:通过 Webpack 或 Vite 插件在构建时扫描源码生成样式,无需预写一大份 CSS。
本框架默认不强制样式方案,以下集成方式适用于使用 Angular CLI(Webpack) 或 Vite 构建 的 Angular 项目。
2. 集成方式概览
| 构建方式 | 推荐集成 | 说明 |
|---|---|---|
| Angular CLI(默认 Webpack) | @angular-builders/custom-webpack + @unocss/webpack | 通过 custom-webpack 注入 UnoCSS 插件 |
Vite(如 @angular/build + Vite) | Vite 官方插件 unocss/vite | 与 Vite 生态一致,配置简单 |
下面分别给出两种方式的安装与配置步骤。
3. 方式一:Angular CLI + Webpack
3.1 安装依赖
pnpm add -D unocss @unocss/webpack
pnpm add -D @angular-builders/custom-webpack
若项目仍使用 Webpack 4,需保证具备 style-loader 与 css-loader(Angular 默认已有)。
3.2 创建 UnoCSS 配置
在项目根目录创建 uno.config.ts:
// uno.config.ts
import { defineConfig, presetUno } from 'unocss';
export default defineConfig({
presets: [presetUno()],
shortcuts: {
'btn': 'px-4 py-2 rounded-lg bg-blue-500 text-white hover:bg-blue-600',
'card': 'p-4 border border-gray-200 rounded-md shadow-sm',
},
});
可按需增加 presetAttributify、presetIcons 或自定义 rules。
3.3 自定义 Webpack 配置
创建 webpack.config.js(或 .ts,需能被子 builder 加载):
// webpack.config.js(UnoCSS v0.59+ 为 ESM,使用动态 import)
module.exports = function () {
return import('@unocss/webpack').then(({ default: UnoCSS }) => ({
plugins: [UnoCSS()],
optimization: {
realContentHash: true,
},
}));
};
若使用较旧版 UnoCSS,可用 CommonJS:
const UnoCSS = require('@unocss/webpack').default;
module.exports = {
plugins: [UnoCSS()],
optimization: { realContentHash: true },
};
3.4 在 angular.json 中启用 custom-webpack
在对应项目的 architect.build 中替换 builder 并指定 custom-webpack 配置:
{
"projects": {
"your-app": {
"architect": {
"build": {
"builder": "@angular-builders/custom-webpack:browser",
"options": {
"customWebpackConfig": {
"path": "./webpack.config.js"
}
}
},
"serve": {
"builder": "@angular-builders/custom-webpack:dev-server",
"options": {
"buildTarget": "your-app:build"
}
}
}
}
}
}
将 your-app 替换为实际项目名;若使用 applicationBuilder(应用型构建),需查看 @angular-builders/custom-webpack 是否支持并选用对应 target。
3.5 引入 UnoCSS 入口样式
在全局样式入口(如 src/styles.scss 或 src/main.ts)中增加:
// main.ts 顶部
import 'uno.css';
或:
// styles.scss
@import 'uno.css';
保证 UnoCSS 生成的样式参与打包。完成后执行 ng build / ng serve,模板中使用的 Uno 类即可生效。
4. 方式二:Vite 构建的 Angular 项目
若项目已迁移到 Vite(例如通过 @angular/build 的 experimental 或社区方案),可直接使用 Vite 插件。
4.1 安装
pnpm add -D unocss
4.2 配置文件
同样在根目录使用 uno.config.ts(同上)。
4.3 Vite 配置
在 vite.config.ts 中:
import UnoCSS from 'unocss/vite';
export default defineConfig({
plugins: [
angular(),
UnoCSS(),
],
});
4.4 入口引入
在 main.ts 或全局样式入口中:
import 'uno.css';
5. 在项目中的使用方式(替代 SCSS 的写法)
5.1 模板中直接使用工具类
原先用 SCSS 写的布局、间距、颜色等,可改为原子类:
<div class="flex items-center justify-between p-4 bg-white rounded-lg shadow">
<h2 class="text-lg font-semibold text-gray-800">标题</h2>
<button class="btn">操作</button>
</div>
btn 在 uno.config.ts 的 shortcuts 中已定义,等同于一组工具类组合。
5.2 与组件 styles 并存
组件内仍可使用 styles: ['...'] 或 styleUrls 写 SCSS;仅把适合原子化的部分移到 class,复杂或组件私有的样式保留在 SCSS 中:
@Component({
selector: 'app-card',
template: `<div class="card p-4">{{ title }}</div>`,
styles: [`
:host { display: block; }
.card { /* 仅保留无法用工具类表达的样式 */ }
`],
})
5.3 响应式与状态变体
UnoCSS 默认支持类似 Tailwind 的断点与状态前缀:
<div class="w-full md:w-1/2 lg:w-1/3 p-2 md:p-4 hover:bg-gray-100">
响应式 + 悬停
</div>
5.4 渐进替代 SCSS 的建议
- 新页面/新组件:优先用 Uno 工具类 + 少量 SCSS(或仅
:host)。 - 旧页面:保留原有 SCSS,仅在新加块或改版时逐步改用类名,避免一次性大改。
- 全局变量:颜色、间距等若原在 SCSS 变量中,可在
uno.config.ts的theme中统一,或继续用 SCSS 变量 + 少量混合使用。
6. 小结
6. 与 AI 全自动开发的取舍(重要说明)
如果你的目标是「主要由 AI Agent 负责自动生成/重构前端代码,人工以需求+审核为主」,不建议在业务层大量直接写原子类,而应将 UnoCSS 控制在「实现层」,把语义与布局抽象交给 SCSS / 设计令牌与组件类名。
6.1 为何大量原子类会削弱 AI 的效果?
- 原子类表达的是实现细节(
bg-xx px-4 py-2),而不是「卡片」「主按钮」「警告 Banner」等语义。 - 当同一种视觉风格在多个页面出现时,如果都用一串类堆出来:
- AI(和人)在生成新代码时更容易「复制粘贴那一长串」,而不是提炼为复用样式;
- 全局风格调整(如改主色/圆角/间距)需要在很多模板里统一替换,自动化重构成本更高。
- 对 AI Agent 来说,语义清晰的类名 / 组件 / 设计令牌,比零散的 class 列表更容易理解和复用。
换句话说:
SCSS + 设计令牌 + 语义化类名 更像是「可被 AI 理解的领域语言」,而全原子类更像是「机器码」,自动化空间会小很多。
6.2 推荐的折中策略
在本平台中,更推荐如下用法:
- 仍以 SCSS + 设计令牌为主:
- 在
tokens/_variables.scss与主题文件中维护颜色、间距、布局等令牌; - 组件层使用语义化类名(如
.card-panel,.btn-primary),这些类再内部使用 Uno 的 shortcuts 或 token; - 让 AI 在生成代码时更多操作「卡片/按钮/布局组件」,而不是「一串原子类」。
- 在
- UnoCSS 负责实现细节与快速实验:
- 在
uno.config.ts内定义少量语义化shortcuts(如btn-primary,card-surface); - 业务模板中优先用 shortcuts/组件类名,仅在极轻量 demo 或一次性页面中直接写原子类。
- 在
这样可以同时兼顾:
- 开发体验:需要时仍可用 Uno 的原子类快速试验样式;
- AI 自动化:大部分语义与布局抽象仍存在于 SCSS / 设计令牌 / 组件类名中,AI 更容易理解与批量生成/重构。
6.3 总结
| 场景 | 更推荐的选择 |
|---|---|
| 人工主导、小型页面快速试验 | 可以更多使用 Uno 原子类,追求开发速度 |
| 中大型项目、希望 AI Agent 高度自动开发 | 以 SCSS + 设计令牌 + 语义类名为主,Uno 作为实现层和 shortcuts,避免在业务模板中到处堆原子类 |
按上述方式集成 UnoCSS,可以在需要时享受原子化的灵活,同时保持「样式语义层」对 AI 友好,便于未来走向更高程度的自动化开发。