文章目录
- 1. postcss是什么
- 2. postcss7
-
- 2.1 编写插件
- 3. postcss8带来的新特性
-
- 3.1 编写插件
- 3.2 更小的节点模块
- 3.3 更快的 CSS 构建
- 4. 注意版本差异带来的问题
-
- 4.1 问题描述
- 4.2 原因
- 5. 资料
1. postcss是什么 PostCSS 是解析器,它将 CSS 解析为对象树(AST)。然后插件改变了这棵树,最后PostCSS 从一个修改过的对象树生成一个新的 CSS 字符串。
PostCSS 不是一个预处理器,也不是一种添加语法糖的方式,它是一个用于创建 CSS 工具的框架,是一个用 JavaScript 插件来转换样式的工具。一个 PostCSS 插件是一个接收并且通常从 PostCSS 解析器转换 CSS AST 的函数。PostCSS 让任何有 JavaScript 经验的人都可以创建自己的插件。
2. postcss7 2.1 编写插件 编写适用于postcss7.x版本的插件语法:
// 需要导入postcss
const postcss = require('postcss');
module.exports = postcss.plugin('postcss-merge2', (opts = {}) => {
return (root, result) => {
root.walkRules(rule => {
...
})
}
})
3. postcss8带来的新特性 插件开发者现在可以在postcss8.0中选择使用一个新的 API,这个 API 可以提高构建速度,并减少其工具的最终用户的依赖大小。
3.1 编写插件 编写适用于postcss8.x的插件使用新的插件 API,不需要导入 PostCSS,会得到所有的类和方法作为函数的第二个参数:
- const { decl: Declaration } = require('postcss')module.exports = {
postcssPlugin: 'postcss-example',
-Once (root) {
+Once (root, { Declaration }) {
…
}
}
module.exports.postcss = true
完整示例:
// 不需要导入postcss
module.exports = (opts = {}) => {
return {
postcssPlugin: 'PLUGIN NAME',
Rule(rule, { Declaration }) {},
Declaration (decl) {}
}
}module.exports.postcss = true
3.2 更小的节点模块 之前,每个插件的依赖关系中都有 PostCSS。这可能会导致在 node_modules 中有多个 PostCSS 副本的问题:
node_modules/
autoprefixer/
node_modules/
postcss/← 重复
stylelint/
node_modules/
postcss/← 重复
postcss-normalize/
node_modules/
postcss/← 重复
postcss8.0将确保在 node_modules 中只有一个 PostCSS 实例。操作步骤是:通过编辑 package.json 将 postcss8移动到 peerDependencies,这样可以控制最终用户的 node_ 模块的大小: 现在,所有插件都将使用相同版本的 postcss 作为依赖。
{
"dependencies": {
-"postcss": "^7.0.10"
},
"devDependencies": {
+"postcss": "^8.0.0"
},
+ "peerDependencies": {
+"postcss": "^8.0.0"
+ }
}
3.3 更快的 CSS 构建 之前每一个 PostCSS 插件都在这棵树中穿行。通常一个插件只是寻找一些属性,但是它仍然需要扫描整个树。如果构建工具中有很多插件(或者你使用一个预设插件,里面有很多插件,比如 postcss-preset-env 或者 stylelint) ,大部分的处理时间都会花在插件上,一遍又一遍地遍历树。
// walkDecls方法将遍历整个树以查找所有声明节点
root.walkDecls(decl => {
if (decl.prop === 'will-change') {
decl.cloneBefore({ prop: 'backface-visibility', value: 'hidden' })
}
})
postcss8.0提供一个用于插件的访问者 API,在postcss8.0中所有插件都可以共享 CSS 树的单次扫描。 它使 CSS 处理速度提高了 20%。 要使用单次扫描,需要删除 root.walk* 调用并将代码移动到插件对象中的 Declaration()、Rule()、AtRule() 或 Comment() 方法。
module.exports = {
postcssPlugin: 'postcss-dark-theme-class',
-Once (root) {
-root.walkAtRules(atRule => {
-// Slow
-})
-}
+AtRule (atRule) {
+// Faster
+}
}
module.exports.postcss = true
4. 注意版本差异带来的问题 4.1 问题描述 现在要编写一个postcss的插件,将css中一个选择器下分开书写的margin、padding等属性合并在一起,并需要将插件集成到现有的项目中去。
?
例如:
div {
margin-top: 10px;
margin-bottom: 10px;
margin-left: 10px;
margin-right: 10px;
/* 合并后 */
margin: 10px;
}
我首先创建了一个新的项目,安装postcss(安装时没有指定版本,它默认会安装最新版,当前postcss的最新版本是8.3.6),查阅资料写插件……写好之后可以正常运行。
但是把插件放到现有的项目中后就失效了,转换不成功。非常奇怪。
后来发现项目中使用的postcss是7.x版本,于是我尝试着将版本升到8,然后插件就可以正常运行了。
?
4.2 原因 前边有介绍到编写postcss7.x的插件语法和postcss8.x的插件语法是不一样的。
如果是新手,要编写postcss插件,那么直接去 postcss官网或者postcss的GitHub仓库查资料,它默认会引导我们使用新的插件语法编写适用于postcss8.x的插件。但是,如果项目中的postcss版本是7.x,使用新语法编写的插件就可能有问题,出现下方错误,提示需要使用postcss的8版本
文章图片
此时有两种解决方法
- 仍然使用新插件语法编写插件,同时将项目中postcss的版本升为8,参考postcss8.0插件迁移指南
- 项目中postcss版本不变,仍然是7.x,此时要使用老的插件语法编写插件,参考postcss7.x版本的插件
?
5. 资料
- PostCSS8.0带来的特性
- PostCSS8.0插件迁移指南
- https://github.com/postcss/postcss/releases/tag/8.0.0
- postcss发展历程
- postcss7.x文档
- postcss8.x文档
- postcss的api?
【JS|postcss7和postcss8的差异】前端学习交流QQ群:862748629 点我加入
推荐阅读
- 前端发展历史|从输入url到看到页面经历了些什么(二)——浏览器渲染
- 前端|CSS【层叠样式表Cascading Style Sheets】
- CSS---引用外部字体(二)---优化
- js|chrome 插件开发指南
- opencv|C++ OpenCV霍夫变换--圆检测
- python|用 Python 绘制个人足迹地图
- JS中this的指向问题(面试题)
- 前端面试题|JavaScript前端经典面试题之ES6面试题汇总es6
- vue|Vue+Electron开发跨平台桌面应用(实战)