CSS预处理器与PostCSS
CSS 预处理器与 PostCSS 🎨
Vite 原生支持 SCSS / Less / Stylus 等主流 CSS 预处理器,无需额外配置即可直接使用。本章我们学习如何与 PostCSS 协同工作,打造一个强大的 CSS 工程化方案。
一、原生支持 💎
Vite 内置了对以下预处理器的支持(仅需安装对应编译器):
| 预处理器 | 编译器 | 安装命令 |
|---|---|---|
| SCSS / Sass | sass | pnpm add -D sass |
| Less | less | pnpm add -D less |
| Stylus | stylus | pnpm add -D stylus |
| PostCSS | postcss | pnpm add -D postcss |
sass vs sass-embedded
Vite 推荐使用 sass-embedded(性能更好)或 sass:
# 方案一:sass(标准版)
pnpm add -D sass
# 方案二:sass-embedded(性能更好,10x 速度)
pnpm add -D sass-embeddedVite 会自动检测并优先使用 sass-embedded。
二、SCSS 使用 💎
基本使用 👻
// src/styles/variables.scss
$primary-color: #2c3e50;
$success-color: #67c23a;
$danger-color: #f56c6c;
$font-size-sm: 12px;
$font-size-md: 14px;
$font-size-lg: 16px;
$spacing-xs: 4px;
$spacing-sm: 8px;
$spacing-md: 16px;
$spacing-lg: 24px;// src/components/Button.scss
@import '@/styles/variables.scss';
.button {
background: $primary-color;
color: #fff;
padding: $spacing-sm $spacing-md;
font-size: $font-size-md;
border-radius: 4px;
border: 0;
cursor: pointer;
&:hover {
opacity: 0.9;
}
&--primary {
background: $primary-color;
}
&--success {
background: $success-color;
}
&--danger {
background: $danger-color;
}
}全局注入 💎
每个组件单独 @import 变量文件比较繁琐。Vite 支持 additionalData 全局注入:
// vite.config.ts
import { defineConfig } from 'vite'
import path from 'node:path'
export default defineConfig({
css: {
preprocessorOptions: {
scss: {
// 每个 .scss/.sass 文件都会自动注入这段代码
additionalData: `@import "@/styles/variables.scss";`,
},
},
},
})// 现在每个 SCSS 文件都能直接使用变量,无需手动 import
.button {
background: $primary-color; // ✅ 直接可用
}多个文件注入 👻
// vite.config.ts
additionalData: `
@import "@/styles/variables.scss";
@import "@/styles/mixins.scss";
@import "@/styles/functions.scss";
`使用 @use 时的不同
如果使用现代 SCSS 模块化(@use / @forward),additionalData 需要用 with 语法:
additionalData: `
@use "@/styles/variables.scss" as *;
`SCSS Modules 💎
Vite 内置支持 CSS Modules,把 SCSS 文件命名为 *.module.scss 即可启用:
// Button.module.scss
.button {
background: $primary-color;
color: #fff;
padding: $spacing-sm $spacing-md;
&__icon {
margin-right: $spacing-xs;
}
&--primary {
background: $primary-color;
}
}<template>
<button :class="[$style.button, $style['button--primary']]">
<span :class="$style.button__icon">+</span>
<slot />
</button>
</template>
<script setup lang="ts">
import $style from './Button.module.scss'
</script>CSS Modules 配置 💎
// vite.config.ts
export default defineConfig({
css: {
modules: {
// 命名风格:camelCase | camelCaseOnly | dashes | dashesOnly
localsConvention: 'camelCaseOnly',
// 类名生成规则
generateScopedName: '[name]__[local]___[hash:base64:5]',
// 全局 CSS Modules(不会被 hash)
globalModulePaths: ['src/styles/global.module.scss'],
},
},
})三、Less 使用 💎
// vite.config.ts
export default defineConfig({
css: {
preprocessorOptions: {
less: {
// 全局变量
globalVars: {
primary: '#2c3e50',
success: '#67c23a',
},
// 全局代码
additionalData: `@import "@/styles/variables.less";`,
// Less 选项
math: 'always', // 始终启用数学运算
},
},
},
})四、Stylus 使用 💎
// vite.config.ts
export default defineConfig({
css: {
preprocessorOptions: {
stylus: {
additionalData: `@import "@/styles/variables.styl";`,
},
},
},
})五、PostCSS 💎
Vite 内置了 PostCSS,但默认不启用任何插件。我们手动配置需要的插件。
安装 👻
pnpm add -D postcss postcss-preset-env autoprefixer cssnano配置方式一:postcss.config.js 👻
// postcss.config.js
module.exports = {
plugins: [
require('postcss-preset-env')({
stage: 2, // 兼容性等级
features: {
'nesting-rules': true,
},
}),
require('autoprefixer')({
overrideBrowserslist: ['> 1%', 'last 2 versions', 'not dead'],
}),
],
}配置方式二:vite.config.ts 内联 👻
// vite.config.ts
export default defineConfig({
css: {
postcss: {
plugins: [
// 写法一:直接传插件
// require('autoprefixer'),
// 写法二:传配置
autoprefixer({
overrideBrowserslist: ['> 1%', 'last 2 versions'],
}),
],
},
},
})常用 PostCSS 插件 💎
| 插件 | 作用 |
|---|---|
postcss-preset-env | 将现代 CSS 转为浏览器兼容的语法 |
autoprefixer | 自动添加浏览器前缀 |
cssnano | CSS 压缩 |
postcss-import | 合并 @import |
postcss-nested | 支持 CSS 原生嵌套语法 |
postcss-custom-properties | 支持 CSS 自定义属性 |
postcss-pxtorem | px 转 rem |
postcss-px-to-viewport | px 转 vw/vh |
移动端适配:px 转 rem 👻
pnpm add -D postcss-pxtorem// postcss.config.js
module.exports = {
plugins: [
require('postcss-pxtorem')({
rootValue: 16, // 根字号
propList: ['*'], // 需要转换的属性
selectorBlackList: ['.no-rem'], // 黑名单
minPixelValue: 2, // 小于 2px 不转换
}),
],
}移动端适配:px 转 vw/vh 👻
pnpm add -D postcss-px-to-viewport// postcss.config.js
module.exports = {
plugins: [
require('postcss-px-to-viewport')({
unitToConvert: 'px', // 要转换的单位
viewportWidth: 750, // 设计稿宽度
unitPrecision: 5,
propList: ['*'],
viewportUnit: 'vw',
fontViewportUnit: 'vw',
selectorBlackList: ['.ignore-vw'],
minPixelValue: 1,
mediaQuery: false,
}),
],
}六、CSS 代码分割 💎
Vite 默认会把 CSS 拆分到独立的 chunk,便于按需加载:
// vite.config.ts
export default defineConfig({
build: {
cssCodeSplit: true, // 默认 true
cssMinify: 'esbuild', // 压缩方式
},
})关闭代码分割
如果想把所有 CSS 合并到一个文件:
build: {
cssCodeSplit: false,
}七、CSS 压缩 💎
Vite 默认使用 esbuild 进行 CSS 压缩。如果需要更激进的压缩,可以切换到 cssnano:
pnpm add -D cssnano// vite.config.ts
export default defineConfig({
build: {
cssMinify: 'esbuild', // 默认,够用
// cssMinify: 'lightningcss', // 更快的压缩
// cssMinify: build => cssnano(build, { preset: 'default' }), // 极致的压缩
},
})八、UnoCSS / Tailwind CSS 💎
UnoCSS 👻
UnoCSS 是 Vite 生态最流行的原子化 CSS 引擎,比 Tailwind 更灵活、更快。
pnpm add -D unocss// vite.config.ts
import UnoCSS from 'unocss/vite'
export default defineConfig({
plugins: [
UnoCSS(),
],
})// uno.config.ts
import { defineConfig, presetUno, presetAttributify, presetIcons } from 'unocss'
export default defineConfig({
presets: [
presetUno(), // Tailwind 兼容
presetAttributify(), // 属性化模式
presetIcons(), // 图标
],
})// main.ts
import 'virtual:uno.css'Tailwind CSS 👻
pnpm add -D tailwindcss postcss autoprefixer
npx tailwindcss init -p// tailwind.config.js
module.exports = {
content: ['./index.html', './src/**/*.{vue,js,ts}'],
theme: {
extend: {},
},
plugins: [],
}/* src/styles/tailwind.css */
@tailwind base;
@tailwind components;
@tailwind utilities;// main.ts
import './styles/tailwind.css'九、SCSS 现代模块化 💎
推荐使用 @use + @forward 替代旧的 @import,更符合现代 SCSS 规范:
_variables.scss 👻
// _variables.scss
$primary: #2c3e50;
$success: #67c23a;
$danger: #f56c6c;_mixins.scss 👻
// _mixins.scss
@use 'variables' as *;
@mixin flex-center {
display: flex;
justify-content: center;
align-items: center;
}
@mixin text-ellipsis($lines: 1) {
@if $lines == 1 {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
} @else {
display: -webkit-box;
-webkit-line-clamp: $lines;
-webkit-box-orient: vertical;
overflow: hidden;
}
}index.scss 👻
// index.scss
@forward 'variables';
@forward 'mixins';组件中使用 👻
// Button.scss
@use '@/styles/variables' as *;
@use '@/styles/mixins' as *;
.button {
background: $primary;
@include flex-center;
@include text-ellipsis;
&:hover {
opacity: 0.9;
}
}常见问题 💎
SCSS 全局变量不生效 👻
- 确认
additionalData配置正确 - 路径要以
~或@/开头(配合 alias) - 重启 dev server
报错:Cannot find module 'sass' 👻
pnpm add -D sassCSS 压缩后类名被压缩 👻
CSS Modules 不会压缩类名(因为通过 JS 引用),但全局 CSS 会被压缩。
PostCSS 配置不生效 👻
- 确认
postcss.config.js在项目根目录 - 确认插件正确安装
- 重启 Vite
小结
本章我们学习了 Vite 中 CSS 工程化的完整内容:
- 原生预处理器支持:SCSS / Less / Stylus
- 全局变量注入:additionalData
- CSS Modules:scoped 样式
- PostCSS:自动前缀、px 转 rem/vw
- UnoCSS / Tailwind:原子化 CSS 框架
- 现代 SCSS:@use / @forward 模块化
下一章我们将学习 路径别名与代理。
至此,本章节的学习就到此结束了,如有疑惑,可对接技术客服进行相关咨询。