什么是PostCSS?
The tool itself is a Node.js module that parses CSS into an abstract syntax tree (AST); passes that AST through any number of “plugin” functions; and then converts that AST back into a string, which you can output to a file.
transform author-friendly stylesheets into browser-friendly CSS
PostCSS可以说是一个将css解析成AST再重新生成css的工具。PostCSS本身不做具体工作,功能都是由插件完成的。插件分析AST,然后重新生成优化的CSS。[1]
Vite中如何使用PostCSS?
vite默认集成了PostCSS,增加一个postcss.config.js
就可以使用插件了。[2]
也可以直接在vite.config.js
的css.postcss
中配置。[3]
export default {
plugins: {
"autoprefixer": {},
"postcss-nested": {},
},
};
用哪些插件?
官网给出的插件列表。[4]
- autoprefixer 自动添加浏览器前缀
- postcss-nested 支持类似SCSS嵌套语法书写
- postcss-sorting 对规则进行排序
- postcss-utilities/short 提供简写,这跟原子化CSS有一定相似之处,可以参
unoCSS
- stylelinter 语法检查
嵌套语法
用vite起一个vanilla项目。[5]
npx create vite@latest my-vanilla-project -- --template vanilla
CSS嵌套语法
import './style.css'
document.querySelector('#app').innerHTML = `
<div class="card">
<p>
hello world!
</p>
</div>
`
.card {
background-color: dodger-blue;
p {
color: red;
user-select: none;
}
}
npm run dev
发现
浏览器原生支持CSS嵌套语法啦![6]
npm run build
查看dist
发现
.card p{color:red;-webkit-user-select:none;user-select:none}
不好!
我们发现了两个问题:1、嵌套语法被铺平了;2、user-select
被加了前缀
原因是build
默认开启了CSSminify
。
export default defineConfig({
build: {
cssMinify: false,
}
})
关闭再build
发现
转换CSS
如果我们需要css代码压缩呢?
cssMinify
目前有两个选择'lightningcss'/'esbuild'
,默认值是'esbuild'
。
cssTaget
默认跟随target
,默认值是'modules'
,代表的是['es2020', 'edge88', 'firefox78', 'chrome87', 'safari14']
。'chrome87'
并不支持原生嵌套,所以做了铺平转换;'safari14'
不支持不带前缀的user-select
,所以加了-webkit-
前缀。
export default defineConfig({
build: {
cssTarget: 'chrome135',
}
})
我们改cssTaget
为'chrome135'
再试试。(具体可选的target参考esbuild官网。[7])
好了,现在的问题解释清楚了。
回到原生CSS嵌套之前
嵌套写法最早源自scss/less
等预处理器,它们提供变量、混入、函数、继承等更多的功能,并最终编译到普通CSS。
postcss-nested
是一个支持书写嵌套语法CSS的后处理器,最终会铺平。
pnpm i postcss-nested
,在postcss.config.js
中增加插件
export default {
plugins: {
"postcss-nested": {},
},
};
npm run dev
发现
好的,被平铺了!
铺平 OR 嵌套?
在开发时嵌套有很好的可读性,方便维护。
在构建时我们要考虑的是:
- 目标平台兼容性,至少要支持原生嵌套,才能考虑是嵌套还是铺平,否则只能铺平
- 产物大小,所以铺平还是嵌套要实际情况决定,一般嵌套会省下重复的父类名
自动前缀
不同浏览器(版本)对CSS标准支持程度不同
-webkit-
: Chrome,Safari-moz-
:firefox-ms-
:IE
添加前缀 OR 去除前缀?
在开发时,我们希望专注于功能,不关心目标平台前缀。
在构建时,我们才需要考虑前缀问题。
- 如果我们希望尽可能多的支持不同平台,应当添加前缀使得“一次编码,四处可用”
- 当我们的目标平台十分确定时,我们应该很明确地删除冗余的前缀,以减小代码size
References
- It's Time for Everyone to Learn About PostCSS | David Clark Develops the Web
- Features | Vite
- Shared Options | Vite
- https://github.com/postcss/postcss?tab=readme-ov-file#plugins
- Getting Started | Vite
- 使用 CSS 嵌套 - CSS:层叠样式表 | MDN
- esbuild - API