🔥Unocss为什么突然火了

Unocss为什么突然火了

前言

UnoCSS是即时原子CSS引擎,其设计具有灵活性和可扩展性。核心是不固执己见的,所有的CSS实用程序都是通过预设提供的。

首先,理解 Unocss 离不开原子化 CSS 的概念:

  • 原子化 CSS: 将样式拆解到最细粒度的单一原子,例如 .m-4 代表 margin: 4px;.text-red 代表 color: red;。开发者通过在 HTML 或 JSX 中组合这些原子类来构建复杂的 UI。

  • 优势: 极高的可复用性、极少的样式冲突、优秀的可维护性、设计约束性强。

  • 传统原子化框架的痛点: 如 Tailwind CSS,需要预先生成完整的 CSS 文件(包含所有可能的类),即使项目中只使用了其中一小部分。这可能导致:

    • 开发环境 CSS 文件体积庞大,影响热更新速度。
    • 生产环境需要配合 PurgeCSS 等工具进行 Tree Shaking,增加构建步骤和复杂度。
    • 自定义主题或添加新规则需要配置复杂的 tailwind.config.js 文件。

Unocss 的核心突破就在于它解决了这些痛点!

Unocss 是什么?

简单来说,Unocss 是一个按需生成原子 CSS 的工具 。它不是一个预先生成所有类的庞大 CSS 文件库,而是一个 引擎

  1. 即时扫描 (On-demand): Unocss 在开发过程中(通过 Vite、Webpack 等构建工具的插件或独立运行时)实时扫描你的源代码(HTML, JS, JSX, Vue, Svelte 等)。
  2. 识别实用类: 它识别出你在代码中实际使用的类名(如 m-4, text-blue-500, hover:bg-gray-100)。
  3. 按需生成 CSS: 只为你实际用到的类 动态生成对应的 CSS 规则。
  4. 注入样式: 将这些生成的、最小化的 CSS 注入到你的页面中。

核心特性与优势

  1. 极致的性能与体积:

    • 开发环境: 热更新(HMR)速度极快,因为只重新生成变化的少量 CSS,而不是操作整个庞大的 CSS 文件。
    • 生产环境: 生成的 CSS 天然就是最小化的,仅包含项目中实际使用的样式规则。无需额外的 PurgeCSS 步骤,构建输出精简到极致。
  2. 高度可定制与可扩展:

    • 预设系统: Unocss 本身非常核心且轻量,其强大功能通过预设 (presets) 实现。官方提供了丰富的预设:

      • @unocss/preset-uno:默认预设,提供最通用的实用程序(类似 Tailwind 的核心功能)。
      • @unocss/preset-wind:提供与 Tailwind CSS v2/v3 高度兼容的类名和规则。
      • @unocss/preset-attributify:革命性的特性,允许以 HTML 属性的方式使用原子类(如 <div text="blue-500 hover:red" m-4>),极大提升可读性和组织性。
      • @unocss/preset-icons:轻松按需使用图标(如 Iconify)。
      • @unocss/preset-typography:提供排版样式。
      • @unocss/preset-web-fonts:轻松引入网络字体。
      • @unocss/preset-tagify:将特定标签自动转换为原子类。
    • 自定义规则: 你可以轻松定义自己的原子类规则。无论是简写、别名还是全新的实用程序,都可以通过简洁的配置实现。

    • 可变修饰: 规则支持动态值(如 m-${size}),并在扫描时匹配和生成对应的 CSS。

  3. 智能与灵活:

    • CSS 指令: 支持在类名中内联编写任意 CSS ([attr:value]),提供突破原子类限制的灵活性。
    • Shortcuts: 允许你将常用的多个原子类组合定义成一个简短的别名,提高代码可读性和编写效率。
    • Layer 排序: 控制生成 CSS 的顺序,解决样式优先级问题。
  4. 框架无关: 虽然与 Vite 集成体验最佳,但也支持 Webpack、Nuxt、Vue CLI、SvelteKit、Astro 等主流前端工具和框架。

  5. 熟悉而现代: 如果你熟悉 Tailwind CSS,那么使用 Unocss 的 preset-wind 会感觉非常亲切,同时又能享受到 Unocss 带来的性能和灵活性提升。

Unocss 是如何工作的?

  1. 集成: 在你的项目中安装 Unocss 核心包和所需的预设,并在构建工具配置(如 vite.config.js)中引入 Unocss 插件。

  2. 配置: 创建一个 unocss.config.ts 文件,选择需要的预设和进行自定义规则、主题、Shortcuts 等配置。

  3. 开发/构建:

    • 当你启动开发服务器 (vite dev) 或进行构建 (vite build) 时:
    • Unocss 插件会监视你的源代码文件。
    • 对文件内容进行扫描,提取出所有匹配预设和自定义规则的类名、属性名等。
    • 根据匹配到的内容,动态生成对应的 CSS 规则。
    • 将这些规则注入到页面的 <style> 标签中(开发环境)或打包到最终的 CSS 文件中(生产环境)。
  4. 使用: 在组件或 HTML 中,像使用普通 CSS 类或属性(如果用了 attributify)一样使用定义好的原子类。

按需生成

Unocss 实现「监视源代码文件并动态插入 CSS」的核心机制主要依赖于构建工具插件(如 Vite、Webpack 等)和其内部的 「按需扫描」引擎。下面详细解释其工作流程和技术原理:

一、核心流程(以 Vite 为例)

  1. 集成插件

    • vite.config.js 中引入 unocss/vite 插件。
    • 插件初始化时会读取你的 unocss.config.ts 配置(预设、规则、主题等)。
  2. 启动开发服务器 (vite dev)

    • Vite 启动开发服务器,并加载 Unocss 插件。
    • Unocss 插件会向 Vite 注册关键的 「构建钩子 (Hooks)」
  3. 文件监听与扫描

    • 监听文件变化

      Vite 本身会监视项目文件(*.html, *.js, *.jsx, *.vue, *.svelte 等)。当任何文件被修改、添加或删除时,Vite 会触发相应的 「热更新 (HMR)」 流程。

    • 拦截文件内容

      Unocss 插件通过注册 Vite 的 transform 钩子拦截 所有源代码文件的处理过程。每当一个文件被 Vite 加载或更新时,Unocss 都能获取到它的 内容 (content)文件路径 (id)

    • 执行扫描

      Unocss 的核心引擎 扫描 (scan) 这些文件的内容:

      • 解析 HTML 标签、属性、类名 (class/className)、Vue/Svelte 模板语法等。

      • 识别其中符合规则的字符串:

        • 预设定义的原子类名 (如 m-4, text-blue-500, hover:bg-gray-100)
        • Attributify 模式下的属性名 (如 text="blue-500", hover:bg="gray-100")
        • Icons 预设的图标类名 (如 i-mdi:home)
        • 自定义规则匹配的字符串
        • 内联 CSS 指令 (如 [color:red])
      • 将这些识别到的 「有效 token」 收集起来。

  4. 按需生成 CSS

    • Unocss 引擎根据收集到的 所有有效 token ,结合配置中的规则 (rules)主题 (theme)Shortcuts动态计算 出对应的 最小化 CSS 规则

    • 这个过程是 增量式 的:

      • 初次启动:扫描所有入口文件及其依赖,生成完整 CSS。
      • 文件更新:只重新扫描变化的文件 ,计算 新增的 token失效的 token增量更新 CSS 规则集。这是 HMR 极快的关键!
  5. 注入 CSS

    • 开发环境:

      • Unocss 插件在 Vite 的 configureServer 钩子中,向开发服务器注入一个 中间件 (Middleware)

      • 这个中间件会拦截一个特定的虚拟请求 (例如 /@unocss.css)。

      • 当浏览器请求这个虚拟 CSS 文件时,中间件会实时返回当前内存中生成的完整 CSS 文本。

      • 在项目的入口 HTML 文件主 JS 文件 中,Unocss 插件会自动添加一个 <link> 标签引入这个虚拟 CSS 文件:

        html 复制代码
        <!-- 自动注入到 HTML 中 -->
        <link rel="stylesheet" href="/@unocss.css">
      • HMR 更新: 当 CSS 规则变化时,Unocss 通过 Vite 的 HMR API 通知浏览器动态更新 这个虚拟样式表,实现无刷新样式更新

    • 生产环境 (vite build):

      • Unocss 插件注册 Vite 的 buildEndgenerateBundle 钩子。
      • 在构建的最后阶段,扫描所有最终打包产物中的文件。
      • 将扫描到的所有 token 生成最终的、最小化的 CSS 字符串
      • 将这个 CSS 字符串作为一个虚拟 CSS 模块 ,通过 Vite 的打包流程输出到最终的 CSS 文件 (如 assets/index.xxxx.css),并自动被入口 HTML 引用。

关键技术点解析

  1. 「按需」的本质:

    • 不是预生成所有可能类: 不像 Tailwind 需要先生成包含所有可能类的巨大 CSS 文件。
    • 运行时扫描 + 动态生成: 只生成代码中实际出现 的类对应的 CSS 规则。这是其体积极致小开发 HMR 极快的根本原因。
  2. 与构建工具深度集成:

    • 利用构建工具的模块图 (Module Graph): Unocss 插件能获取 Vite 处理的所有模块及其依赖关系 。这确保了即使类名是动态生成的(如 class="text-${color}-500"),只要 color 的可能值在代码中被静态引用过,Unocss 也能正确扫描到并生成对应的 CSS (如 text-red-500, text-blue-500)。
    • 利用构建工具的 HMR API: 实现 CSS 的即时、精准更新。
  3. 虚拟模块 (Virtual Modules):

    • /@unocss.css 是一个典型的虚拟模块 。它不存在于物理磁盘上,而是由 Unocss 插件在内存中动态生成内容并提供给 Vite 服务器或构建流程。
    • 构建工具将虚拟模块当作普通文件处理,简化了集成。
  4. 高效的扫描引擎:

    • Unocss 的核心引擎 (@unocss/core) 实现了高效的字符串匹配算法CSS 规则生成器
    • 它根据配置的规则(静态规则、正则表达式规则、动态规则)快速匹配文件内容中的 token。
    • 增量扫描确保只处理变更部分,性能开销极小。
  5. 支持多种语法:

    • 引擎不仅能扫描 class 属性,还能处理 Vue/Svelte 的模板语法、JSX 中的 className、Attributify 模式的属性、甚至纯 JS 字符串(通过特定注释或约定)。
    • 插件内部包含针对不同文件类型(.vue, .jsx, .svelte 等)的解析器。

Playground

unocss.dev/play/

相关推荐
江城开朗的豌豆14 分钟前
前端性能救星!用 requestAnimationFrame 丝滑渲染海量数据
前端·javascript·面试
江城开朗的豌豆14 分钟前
src和href:这对'双胞胎'属性,你用对了吗?
前端·javascript·面试
江城开朗的豌豆21 分钟前
forEach遇上await:你的异步代码真的在按顺序执行吗?
前端·javascript·面试
万少29 分钟前
HarmonyOS Next 弹窗系列教程(3)
前端·harmonyos·客户端
七灵微2 小时前
【后端】单点登录
服务器·前端
持久的棒棒君5 小时前
npm安装electron下载太慢,导致报错
前端·electron·npm
crary,记忆7 小时前
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
前端·webpack·angular·angular.js
漂流瓶jz8 小时前
让数据"流动"起来!Node.js实现流式渲染/流式传输与背后的HTTP原理
前端·javascript·node.js
SamHou08 小时前
手把手 CSS 盒子模型——从零开始的奶奶级 Web 开发教程2
前端·css·web
我不吃饼干8 小时前
从 Vue3 源码中了解你所不知道的 never
前端·typescript