JS|postcss7和postcss8的差异


文章目录

  • 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版本
JS|postcss7和postcss8的差异
文章图片

此时有两种解决方法
  1. 仍然使用新插件语法编写插件,同时将项目中postcss的版本升为8,参考postcss8.0插件迁移指南
  2. 项目中postcss版本不变,仍然是7.x,此时要使用老的插件语法编写插件,参考postcss7.x版本的插件
总结:为 postcss7.x创建的插件适用于 postcss8.x,但是为postcss8.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 点我加入

    推荐阅读