UnoCSS Nuxt 集成实战:@unocss/nuxt 模块安装、uno.config 配置与多层合并原理
【免费下载链接】unocssThe instant on-demand atomic CSS engine.项目地址: https://gitcode.com/GitHub_Trending/un/unocss
在 Nuxt 项目中使用 UnoCSS 的官方方式是安装 Nuxt Module@unocss/nuxt:它会自动向应用注入uno.css虚拟入口,把 UnoCSS 的 Vite/Webpack 插件接入 Nuxt 的构建管线,并支持通过 Nuxt Layers 自动合并多个uno.config配置文件。读完本篇,你可以完成@unocss/nuxt的安装与注册、用uno.config.ts或模块选项两种方式进行配置,并理解该模块在build:before阶段如何加载配置、注入插件以及处理 cssnano 等底层细节。
安装与模块注册
在 Nuxt 项目根目录执行以下命令(以 pnpm 为例,yarn/npm/bun 同理):
pnpm add -D unocss @unocss/nuxt在nuxt.config.ts的modules数组中注册@unocss/nuxt:
export default defineNuxtConfig({ modules: [ '@unocss/nuxt', ], })从源码看,该模块通过defineNuxtModule定义,meta.configKey为unocss,意味着所有模块选项都可以直接写在nuxt.config.ts的unocss字段下,并获得类型提示(模块在 入口文件 中同时向@nuxt/schema注入了NuxtConfig.unocss的类型声明)。
自动注入 uno.css 入口
文档强调 "uno.cssentry will be automatically injected by the module"。实现上,当autoImport开启时(默认开启),模块会调用addPluginTemplate生成一个虚拟插件模板unocss.mjs,其内容取决于mode选项:
// packages-integrations/nuxt/src/index.ts(addPluginTemplate 的 getContents 逻辑) const lines = [ InjectModes.includes(options.mode) ? 'import \'uno.css\'' : '', 'import { defineNuxtPlugin } from \'#imports\'; export default defineNuxtPlugin(() => {})', ] if (options.preflight) lines.unshift('import \'@unocss/reset/tailwind.css\'')其中InjectModes为['global', 'dist-chunk'],即只有这两种模式会真正import 'uno.css'(per-module等模式由插件自行决定注入方式)。mode的类型完整定义为'global' | 'per-module' | 'vue-scoped' | 'dist-chunk' | 'shadow-dom',见 Vite 插件类型定义。
若开启preflight选项,模板会在最前面追加import '@unocss/reset/tailwind.css',无需再手动引入 reset。此外模块默认会设置nuxt.options.features.inlineStyles = false(由disableNuxtInlineStyle控制),关闭 Nuxt 的 inlineStyle 特性,使其与 UnoCSS 的按需扫描互不干扰。
自动安装 UnoIcon 组件
components选项默认开启,模块会通过addComponentsDir注册 runtime 目录,让<UnoIcon>组件支持 Nuxt 的组件自动导入(例如<UnoIcon name="i-carbon-car" class="text-2xl" />可直接使用而不必手动 import)。
模块选项速览
所有选项类型定义在 options 类型文件,UnocssNuxtOptions继承自@unocss/core的UserConfig(即支持完整的 UnoCSS 配置项),并额外扩展以下 Nuxt 专属字段(默认值取自 模块默认值):
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
mode | VitePluginConfig['mode'] | 'global' | CSS 生成模式,仅对 Vite 生效 |
autoImport | boolean | true | 自动注入uno.css虚拟入口 |
preflight | boolean | false | 自动注入@unocss/reset/tailwind.css |
disableNuxtInlineStyle | boolean | true | 自动关闭 Nuxt 的features.inlineStyle |
components | boolean | true | 自动安装<UnoIcon>组件 |
nuxtLayers | boolean | false | 自动合并各 Nuxt 层中的 UnoCSS 配置 |
injectPosition | 'first' \| 'last' \| number \| { after? } | 'first' | 已临时移除:源码中检测到该选项会打印警告,因与 Nuxt 3.9 不兼容暂时不生效 |
wind3 | boolean \| PresetWind3Options | true | 启用 wind3 preset(简写) |
wind4 | boolean \| PresetWind4Options | false | 启用 wind4 preset(简写) |
attributify | boolean \| AttributifyOptions | false | 启用 attributify preset(简写) |
tagify | boolean \| TagifyOptions | false | 启用 tagify preset(简写) |
icons | boolean \| IconsOptions | false | 启用 icons preset(简写) |
webFonts | boolean \| WebFontsOptions | false | 启用 web-fonts preset(简写) |
typography | boolean \| TypographyOptions | false | 启用 typography preset(简写) |
preset 简写选项的解析逻辑在 resolveOptions 中,有两个关键行为:
- wind3 与 wind4 互斥:若同时开启,会打印警告
[unocss/nuxt]: wind3 and wind4 presets are mutually exclusive. wind3 will be disabled in favor of wind4.,并自动禁用wind3,以wind4为准; - 仅在未显式配置
presets时生效:若你在uno.config.ts或unocss选项中提供了presets数组,则这些简写布尔项全部忽略,以显式presets为准。每个简写项都支持传对象以透传 preset 自己的选项,如icons: { collections: ['carbon', 'mdi'] }。
resolveOptions还会为content.pipeline.exclude追加默认排除项:来自 默认管线排除集 的cssIdRE(排除?vue&type=style等虚拟 CSS 片段),并额外 push/\?macro=true/以忽略 Nuxt 生成的 macro 文件,避免把宏文件内容误当作待扫描的 class 来源。
配置文件:推荐独立 uno.config.ts
官方推荐把 UnoCSS 配置写在项目根目录独立的uno.config.ts文件中(而非全部塞进nuxt.config.ts),详见 Config File 指南:
import { defineConfig } from 'unocss' export default defineConfig({ // ...UnoCSS options })模块选项同样支持configFile(继承自UserConfig),用于指定非默认位置的配置文件。在build:before钩子中,模块通过createRecoveryConfigLoader(来自 @unocss/config)完成配置加载:
// packages-integrations/nuxt/src/index.ts(build:before 钩子,节选) nuxt.hook('build:before', async () => { const { config: unoConfig } = await loadConfig( process.cwd(), { configFile: options.configFile }, [], options, ) // ... await nuxt.callHook('unocss:config', unoConfig) extendViteConfig(async (config) => { const { default: VitePlugin } = await import('@unocss/vite') config.plugins = config.plugins || [] config.plugins.unshift(...VitePlugin({ mode: options.mode }, unoConfig)) }) extendWebpackConfig(async (config) => { const { default: WebpackPlugin } = await import('@unocss/webpack') config.plugins = config.plugins || [] config.plugins.unshift(WebpackPlugin({}, unoConfig)) }) })从源码结构看,其调用链为:build:before→ 加载并合并uno.config与模块内联选项 → 触发 Nuxt 钩子unocss:config(供其他模块二次修改最终配置,该钩子也在 类型声明 中注册到NuxtHooks)→ 分别通过extendViteConfig/extendWebpackConfig把@unocss/vite或@unocss/webpack插件unshift到插件列表最前。
一个细节:当 Nuxt 3/4 使用 Vite 构建、且配置中启用了非pre阶段的@unocss/transformer-directives时,模块会改写 cssnano 配置,关闭mergeRules、normalizeWhitespace、discardComments三项优化——源码注释解释了原因:这些优化在 UnoCSS 指令尚未转换前执行会产出无效 CSS。这解释了为何含@apply/@theme等指令指令的项目在 Nuxt 生产构建中不会出现样式丢失。
nuxtLayers:自动合并多层 UnoCSS 配置
在 Nuxt 3 的多层(layers)项目中,每个层可以有自己独立的uno.config。开启nuxtLayers选项后,Nuxt 会自动把各层的配置文件合并为一个生成配置:
export default defineNuxtConfig({ // ... unocss: { nuxtLayers: true, }, })模块内部通过addTemplate生成.nuxt/uno.config.mjs模板(write: true,实际落盘)。从源码逻辑看,它会取nuxt.options._layers.slice(1)中的每个层,用findPath在层目录内查找uno.config/unocss.config,然后按层顺序 reverse 后生成如下形式的文件:
// 生成的 .nuxt/uno.config.mjs 结构(示意) import { mergeConfigs } from '@unocss/core' import cfg0 from '.../base/uno.config.ts' import cfg1 from '.../ui/uno.config.ts' export default mergeConfigs([cfg0, cfg1])生成后,在根配置的uno.config.ts中直接 reexport 即可:
import config from './.nuxt/uno.config.mjs' export default config或者用mergeConfigs在合并结果之上做覆盖/扩展:
import { mergeConfigs } from '@unocss/core' import config from './.nuxt/uno.config.mjs' export default mergeConfigs([config, { // your overrides }])仓库中的 examples/nuxt3-layers 是完整的可运行示例:根配置通过extends: ['./ui', './base']引入两个层,开启nuxtLayers: true,根 uno.config.ts 仅两行 reexport;而 base 层 与 ui 层 各自声明了独立 rule(foo与bar),验证了合并后两层规则同时生效。
完整示例:Nuxt 3 基础用法
仓库的 examples/nuxt3 演示了把配置直接写在unocss选项里的用法:
export default defineNuxtConfig({ modules: [ '@unocss/nuxt', ], unocss: { attributify: true, // 开启 attributify 简写 icons: true, // 开启 icons 简写 components: false, // 不需要 UnoIcon 自动导入 shortcuts: [ ['btn', 'px-4 py-1 rounded inline-block bg-teal-600 text-white cursor-pointer hover:bg-teal-700 disabled:cursor-default disabled:bg-gray-600 disabled:opacity-50'], ], }, })对应页面同时展示了 attributify、图标与 shortcut 三种能力,并在<style>中手动引入 reset(此例未开preflight选项):
<template> <main class="py-20 px-12 text-center"> <span text="blue 5xl hover:red" cursor="default">Hello Nuxt 3</span> <div i-carbon-car text-4xl inline-block /> <button btn>Button</button> </main> </template> <style> @import '@unocss/reset/tailwind.css'; </style>开发时还有一项体验增强:在 dev 模式下,模块监听 Nuxt 的devtools:customTabs钩子,向 Nuxt DevTools 面板中推入一个名为UnoCSS的 iframe 标签页(指向/__unocss/),即内置 Inspector 可视化调试界面,无需额外安装。
支持状态
| Nuxt 2 | Nuxt Bridge | Nuxt 3 | |
|---|---|---|---|
| Webpack Dev | ✅ | ✅ | 🚧 |
| Webpack Build | ✅ | ✅ | ✅ |
| Vite Dev | - | ✅ | ✅ |
| Vite Build | - | ✅ | ✅ |
Nuxt 3 官方推荐走 Vite 构建路径;Webpack 构建在 Nuxt 3 下同样受支持,而 Webpack 开发模式在 Nuxt 3 下标注为进行中。
小结
@unocss/nuxt的核心工作可以概括为三件事:注入(autoImport生成uno.css入口、preflight注入 reset、components注册UnoIcon)、构建接入(build:before中加载uno.config,并把 Vite/Webpack 插件前置注入,同时处理 cssnano 与 directives 的兼容问题)、分层合并(nuxtLayers自动生成.nuxt/uno.config.mjs合并各层配置)。日常使用只需两步——安装模块、写一份uno.config.ts——即可获得开箱即用的按需原子类能力,其余选项均针对特定场景按需开启。
【免费下载链接】unocssThe instant on-demand atomic CSS engine.项目地址: https://gitcode.com/GitHub_Trending/un/unocss
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考