ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Nuxt 样式指南:css 配置、预处理器、PostCSS 与 SFC 样式的完整解析

Nuxt 样式指南:css 配置、预处理器、PostCSS 与 SFC 样式的完整解析 Nuxt 样式指南css 配置、预处理器、PostCSS 与 SFC 样式的完整解析【免费下载链接】nuxtthe full-stack Vue framework项目地址: https://gitcode.com/GitHub_Trending/nu/nuxtNuxt 对样式方案保持不持立场的开放态度你可以手写本地样式表、引入 npm 分发的 CSS 库、加载外部 CDN 样式也可以自由使用 SCSS/Less/Stylus 等预处理器和 PostCSS。本篇以 Nuxt 官方文档的 Styling 章节为骨架逐条覆盖其全部实操路径并结合本仓库中 Vite 构建插件与配置 schema 的源码解释css配置项、PostCSS 插件排序、样式内联inline styles等机制在 Nuxt 4 源码中的真实实现帮助你在实际项目中既会用、也懂其底层。本地样式表Local Stylesheets如果你在编写本地样式表按约定应放在app/assets/目录下。Nuxt 提供两种引入方式在组件内直接引入可以在页面、布局和组件中直接用 JavaScript import 或 CSSimport语句引入样式表script // 静态 import服务端渲染SSR兼容 import ~/assets/css/first.css // 注意动态 import 不兼容服务端渲染 import(~/assets/css/first.css) /script style import url(~/assets/css/second.css); /style官方文档在此处给出了一条重要提示这些样式表会被内联到 Nuxt 渲染的 HTML 中。这一点在源码中可以得到印证——应用入口 entry.ts 会导入#build/css该虚拟模块由 templates.ts 中的cssTemplate生成内容就是nuxt.options.css中每一项的 import 语句拼接export const cssTemplate: NuxtTemplate { filename: css.mjs, dependsOn: [], getContents: ctx ctx.nuxt.options.css.map(i genImport(i)).join(\n), }而在构建阶段Vite 插件 SSRStylesPlugin 会在生产构建时将组件样式以style标签内联进 SSR 响应并在样式已内联时安全地从 HTML 中移除对应的link避免样式重复加载。通过css配置属性全局引入除了组件内引入还可以用 Nuxt 配置中的css属性声明全局样式表——同样建议放在app/assets/目录export default defineNuxtConfig({ css: [~/assets/css/main.css], })同样地这些样式表会被内联进 Nuxt 渲染的 HTML并作为全局样式注入出现在所有页面中。css属性在源码中的处理细节值得注意配置解析schema 定义见 app.ts 中的css字段$resolve会把非数组输入归一化为空数组且只保留字符串类型的条目。去重模块加载完成后Nuxt 会对nuxt.options.css去重见 nuxt.ts 中modules:done钩子之后执行的filter逻辑。由于模块和多层layers都会向css追加条目去重能保证同一张样式表不被重复引入。不可解析路径的告警nuxt.ts 中的warnUnresolvableGlobalCss会检查每个css条目——相对路径条目以./或../开头会直接报错诊断并提示改用~/别名别名解析后不存在于文件系统的条目也会触发诊断。注释明确说明了原因这类错误在其他情况下是静默失败的——开发服务器会发出一个没有任何服务承载的linkURL而生产构建则会把样式整个丢掉。因此配置css时请使用~/assets/...这类可解析的别名路径并留意启动日志中的相关诊断。字体文件Fonts将本地字体文件放入public/目录例如public/fonts然后在样式表中用url()引用font-face { font-family: FarAwayGalaxy; src: url(/fonts/FarAwayGalaxy.woff) format(woff); font-weight: normal; font-style: normal; font-display: swap; }之后在样式表、页面或组件中按字体名使用style h1 { font-family: FarAwayGalaxy, sans-serif; } /stylepublic/目录中的文件以原始文件名直接通过根 URL 提供如/fonts/xxx.woff不经过构建工具处理这与需要处理的app/assets/目录形成对照后者不会被暴露为静态 URL。通过 NPM 分发的样式表也可以引用 npm 分发的样式表。以流行的animate.css为例安装npm install animate.css # 或 yarn add / pnpm install / bun install / deno install npm:animate.css然后在页面、布局或组件中直接引用script import animate.css /script style import url(animate.css); /style也可以在 Nuxt 配置的css属性中以字符串形式引用包名export default defineNuxtConfig({ css: [animate.css], })外部样式表External Stylesheets外部样式表包括本地样式表还可以通过向head注入link元素的方式引入最常用的方式是 Nuxt 配置的app.head属性export default defineNuxtConfig({ app: { head: { link: [{ rel: stylesheet, href: https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css }], }, }, })动态添加样式表在代码中可以使用useHeadcomposable 动态设置 head 内容useHead({ link: [{ rel: stylesheet, href: https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css }], })Nuxt 底层使用的是unhead完整能力可参考其文档。用 Nitro 插件修改渲染后的 Head如果需要更精细的控制可以用钩子拦截渲染后的 HTML 并编程式地修改 head。在~~/server/plugins/my-plugin.ts中创建一个插件import { definePlugin } from nitro export default definePlugin((nitro) { nitro.hooks.hook(render:html, (html) { html.head.push(link relstylesheet hrefhttps://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css) }) })需要记住的是外部样式表是渲染阻塞render-blocking资源——浏览器必须加载并处理完它们才能渲染页面。含有不必要大型样式表的页面渲染会更慢应尽量避免引入过大的外部 CSS。使用预处理器Preprocessors要使用 SCSS、Sass、Less 或 Stylus 等预处理器先安装对应依赖npm install -D sass # Sass SCSS npm install -D less # Less npm install -D stylus # Stylus样式表按约定写在app/assets目录然后在app.vue或布局文件中用预处理器语法引入源文件style langscss use ~/assets/scss/main.scss; /style或者同样使用 Nuxt 配置的css属性export default defineNuxtConfig({ css: [~/assets/scss/main.scss], })两种方式下编译后的样式表都会内联进 Nuxt 渲染的 HTML。向预处理文件注入代码partial 变量如果需要向预处理文件注入代码例如包含颜色变量的 Sass partial可以在 Vite 的 preprocessorOptions 中配置。先在app/assets目录创建 partial$primary: #49240F; $secondary: #E4A79D;$primary: #49240F $secondary: #E4A79D然后在nuxt.config中配置additionalDataSCSS 与 SASS 各自对应不同的键// SCSS export default defineNuxtConfig({ vite: { css: { preprocessorOptions: { scss: { additionalData: use ~/assets/_colors.scss as *;, }, }, }, }, })// SASS export default defineNuxtConfig({ vite: { css: { preprocessorOptions: { sass: { additionalData: use ~/assets/_colors.sass as *\n, }, }, }, }, })Nuxt 默认使用 Vite。如果改用 webpack请参考各预处理器 loader 的文档自行配置。预处理器 Worker实验性Vite 提供了一个实验性选项css.preprocessorMaxWorkers可以为预处理器提速。可以在nuxt.config中开启export default defineNuxtConfig({ vite: { css: { preprocessorMaxWorkers: true, // number of CPUs minus 1 }, }, })这是实验性选项使用前建议查阅 Vite 官方文档并了解其反馈渠道。单文件组件SFC样式Vue SFC 天然擅长处理样式可以直接在组件的style块中写 CSS 或预处理器代码无需 CSS-in-JS 即可获得很好的开发体验如果确实想使用 CSS-in-JS也有第三方库和 Nuxt 模块可选。Class 与 Style 绑定可以利用 Vue SFC 的 class/style 绑定特性来动态控制组件样式。文档给出了三类写法ref/reactive 对象绑定、computed 计算绑定、数组绑定以及对象/数组形式的:style绑定script setup langts const isActive ref(true) const hasError ref(false) const classObject reactive({ active: true, text-danger: false, }) /script template div classstatic :class{ active: isActive, text-danger: hasError } / div :classclassObject / /templatescript setup langts const isActive ref(true) const error ref(null) const classObject computed(() ({ active: isActive.value !error.value, text-danger: error.value error.value.type fatal, })) /script template div :classclassObject / /templatescript setup langts const isActive ref(true) const errorClass ref(text-danger) /script template div :class[{ active: isActive }, errorClass] / /templatescript setup langts const activeColor ref(red) const fontSize ref(30) const styleObject reactive({ color: red, fontSize: 13px }) /script template div :style{ color: activeColor, fontSize: fontSize px } / div :style[baseStyles, overridingStyles] / div :stylestyleObject / /template用v-bind实现动态样式在style块中可以用v-bind引用 JavaScript 变量和表达式绑定是动态的——变量值变化时样式会随之更新script setup langts const color ref(red) /script template div classtext hello /div /template style .text { color: v-bind(color); } /styleScoped 作用域样式scoped属性让你可以隔离地给组件写样式声明只作用于当前组件template div classexample hi /div /template style scoped .example { color: red; } /styleCSS Modules通过module属性使用 CSS Modules通过注入的$style变量访问生成的类名template p :class$style.red This should be red /p /template style module .red { color: red; } /styleSFC 中的预处理器支持SFC 的style块支持预处理器语法。Vite 内置支持.scss、.sass、.less、.styl和.stylus文件无需配置安装依赖后即可直接在 SFC 中通过lang属性使用style langscss /* Write scss here */ /stylestyle langsass /* Write sass here */ /stylestyle langless /* Write less here */ /stylestyle langstylus /* Write stylus here */ /stylewebpack 用户请参考 vue-loader 的文档。使用 PostCSSNuxt 内置 PostCSS可以在nuxt.config中配置export default defineNuxtConfig({ postcss: { plugins: { postcss-nested: {}, postcss-custom-media: {}, }, }, })在 SFC 中可以使用langpostcss属性获得更好的语法高亮style langpostcss /* Write postcss here */ /styleNuxt 默认预配置了以下 PostCSS 插件postcss-import增强import规则postcss-url转换url()语句autoprefixer自动添加厂商前缀cssnano压缩与 purge源码层面PostCSS 的解析与排序逻辑集中在 css.ts 的resolveCSSOptions中并被 vite.ts 在创建 Vite 配置时调用css: await resolveCSSOptions(nuxt)。其关键行为有插件排序postcss.order支持字符串预设名、数组或函数三种形态定义见 postcss.ts。默认预设是autoprefixerAndCssnanoLast即强制autoprefixer和cssnano排在所有插件最后——这是刻意为之autoprefixer 需要看到最终选择器cssnano 作为压缩器必须最后执行。缺失插件的交互式安装resolvePostcssPlugin会尝试从modulesDir导入插件导入失败时会调用ensureDependencyInstalled提示用户安装该依赖若用户拒绝则发出NUXT_B7007构建诊断含安装命令而不会让构建莫名失败。这意味着在postcss.plugins中只需写插件名与选项对象Nuxt 会替你完成解析 → 排序 → 实例化的整个流程。用布局Layouts承载多套样式如果应用的不同部分需要完全不同的风格可以使用布局为不同布局编写不同样式。template div classdefault-layout h1Default Layout/h1 slot / /div /template style .default-layout { color: red; } /style布局机制详见官方文档中 app/layouts 目录结构说明。第三方库与模块Nuxt 对样式方案不持立场可以使用任何工具例如 UnoCSS、Tailwind CSS 等流行库。社区和 Nuxt 团队开发了大量 Nuxt 模块来简化集成常见的有UnoCSS即时的按需原子化 CSS 引擎Tailwind CSS原子优先utility-firstCSS 框架Fontaine字体度量回退font metric fallback可减少 CLSPinceau可适配的样式框架Nuxt UI面向现代 Web 应用的 UI 库Panda CSS构建时生成原子化 CSS 的 CSS-in-JS 引擎Nuxt 模块开箱即用地提供了好的开发体验但要记住即使你偏好的工具没有现成模块也完全可以用 Nuxt 插件、或自行编写模块的方式接入。如果自行做了集成欢迎分享回社区。便捷加载 Web 字体可以使用 Nuxt Google Fonts 模块加载 Google Fonts如果使用 UnoCSS它自带 web fonts preset可从 Google Fonts 等常见字体提供商便捷加载字体。进阶话题过渡TransitionsNuxt 拥有与 Vue 相同的Transition组件并支持实验性的 View Transitions API。字体高级优化官方推荐使用 Fontaine 模块降低 CLS累计布局偏移如需更高级的控制可以考虑编写 Nuxt 模块来扩展构建流程或运行时。LCP 高级优化要加快全局 CSS 文件的下载官方建议使用 CDN让文件在物理上更接近用户压缩资源理想情况下使用 Brotli使用 HTTP2/HTTP3 传输将资源托管在同一域名下不要使用不同的子域名如果使用 Cloudflare、Netlify 或 Vercel 等现代平台上述大多数事情通常会自动完成。如果所有 CSS 都已由 Nuxt 内联还可以实验性地完全阻止渲染后的 HTML 中引用外部 CSS 文件——通过build:manifest钩子实现钩子可以放在模块中也可以直接写在 Nuxt 配置文件中export default defineNuxtConfig({ hooks: { build:manifest: (manifest) { // find the app entry, css list const css Object.values(manifest).find(options options.isEntry)?.css if (css) { // start from the end of the array and go to the beginning for (let i css.length - 1; i 0; i--) { // if it starts with entry, remove it from the list if (css[i].startsWith(entry)) { css.splice(i, 1) } } } }, }, })从源码结构看这个钩子的存在与features.inlineStyles机制是一脉相承的默认情况下 Nuxt 就会把组件与全局样式内联为style标签SSRStylesPlugin 甚至会在某个 CSS 文件的所有来源都已被内联时自动从 client manifest 中丢弃对应的link并在渲染阶段按请求条件ssrContext.modules中实际渲染了哪些组件决定某条样式链接是否可安全省略。手动操作build:manifest是对该自动化之外的进一步控制手段使用前应确认内联范围确实覆盖了全部样式。小结Nuxt 的样式体系可以归纳为四层引入层组件内import/import、css配置全局引入、app.head/useHead注入link、Nitrorender:html钩子兜底处理层Vite 内置预处理器支持、preprocessorOptions注入 partial、PostCSS 插件含默认排序与缺失提示渲染层样式内联进 SSR HTMLfeatures.inlineStyles与SSRStylesPlugin的去重逻辑、外部样式表的渲染阻塞成本扩展层布局隔离多套样式、第三方 CSS 框架/模块、字体加载与 LCP 优化手段。掌握这些你就能在 Nuxt 项目中按场景选择最合适的样式方案并在需要时基于packages/vite/src/css.ts、packages/vite/src/plugins/ssr-styles.ts与packages/schema/src/config/postcss.ts等源码位置继续深挖其构建行为。【免费下载链接】nuxtthe full-stack Vue framework项目地址: https://gitcode.com/GitHub_Trending/nu/nuxt创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表