PostCSS和一些有兴趣的东西
PostCSS是一个很有趣的项目。简而言之,它将CSS转换成抽象语法树(AST),也就是JavaScript可以操作的一种数据形式。基于JavaScript的PostCSS插件可以执行不同的代码操作。PostCSS本身并没有改变你的CSS,它请允许插件执行和转换你的代码。
实际上,对于CSS的操作,PostCSS插件并没有任何限制。只要你有想得到的,你都可以写一个PostCSS插件来实现。
重要的是要知道PostCSS是什么?@Envato-tuts写了一个有关于深入学习PostCSS系列教程,其中有一篇就是关于PostCSS需要知道哪些?
有关于《深入学习PostCSS》,我们也翻译了一些,但整个系列没有译完,如果不喜欢看英文的,可以点击这里。
PostCSS不是一个预处理器
是的,你可以绝对地使用它作为预处理器,但你也可以在没有任何预处理器功能的情况下使用PostCSS。比如我只使用Autoprefixer和CSS Nano。而这些都不是预处理器。
PostCSS不是一个后处理器
后处理器常被看作是处理一个完成了的样式表,比如处理CSS样式中的有效的,标准的CSS语法规则,如果发现不符合,做相应的处理。比如说添加浏览器的私有前缀。然而,PostCSS可以做这些事情,但它绝不仅仅是处理文件,只不过是受你使用的插件限制而以。
PostCSS不是新语法
有一些很好的,非常有名的PostCSS插件,允许你在代码中使用未来的语法,也就是说使用将来可用的CSS属性,但这些属性现在还没有得到广泛的支持。然而,PostCSS本身并不是只用来支持未来语法的。
是否使用未来的语法是你的选择,而不是需求。我是使用SCSS的,我做了一些特殊的功能处理,并在一个功能中使用PostCSS。如果我如此选择,我可以转向PostCSS,并且使用未来的特性,而不用担心浏览器是否支持。
PostCSS不是一个清理或优化的工具
Autoprefixer插件成功的导致了PostCSS的普遍看法,认为是在完成了CSS之后再来清理,并且优化的,让属性能得到跨浏览器的兼容性。
当然,有很多很优秀的插件可以提供清理和优化相关的功能,但这些也只是一些可用的插件而以。
我为什么选择PostCSS?
我最初决定不使用PostCSS,直到我发现Autoprefixer和CSSNano一些我喜欢的工具,实际上是PostCSS插件。这让我开始研究PostCSS本身,看看它到底是什么。我发现的是一个基本工具和丰富的生态系统插件,可以做很多你可能想要的事情,比如说你的CSS前添加前缀是根据BEM这样的规则。
我也喜欢@Martin提出的单一责任原则:
单一责任原则是一种计算机编程原理,它指出每个模块或类都应该对应软件提供的功能的一部分责任,并且这个责任应该完全由类来封装。
基本上,每个PostCSS插件只处理一个任务,并且把这个任务做好。我们不应该创建那些不止一件事情的类,我们也不应该重复使用国一个PostCSS插件来处理已经可以使用的功能。
在这篇文章中,我们将探讨如何使用Gulp构建一个PostCSS工作流,如何构建一个插件以及如保将插件添加到我们已创建好的PostCSS工作流中。
运行PostCSS
我主要在一个Gulp环境中工作,我构建了PostCSS插件中的Autoprefixer这个任务,自动添加浏览器的私有前缀。假设你之前没有做过,那么你需要安装一全局的Gulp:
npm i -g gulp
然后需要安装我们要的插件:gulp
、postcss
和autoprefixer
。进入你正在开发的项目,像下面那样安装这些插件,其中-D
表示将要安装的插件保存为开发依赖项。
npm i -D gulp gulp-postcss autoprefixer
这项任务目前由两部分组成:
- 使用的处理器列表
- 任务本身
该任务通过sourcemaps
输入,然后运行已配置的PostCSS和Autoprefixer,并配置好浏览器版本。然后,它将sourcemaps
和输出写入到目标文件夹中:
gulp.task("processCSS", () => {
// What processors/plugins to use with PostCSS
const PROCESSORS = [
autoprefixer({browsers: ['last 3 versions']})
];
return gulp
.src("src/css/**/*.css")
.pipe($.sourcemaps.init())
.pipe(postcss(PROCESSORS))
.pipe($.sourcemaps.write("."))
.pipe(gulp.dest("src/css"))
.pipe($.size({
pretty: true,
title:
"processCSS"
}));
});
如果我们在CSS处理过程中最后运行这个任务,我们可以将目标从src/css
更改为dest/css
,但是这个任务第一次使用的过程有一个额外的任务,就是压缩代码的任务,这是超出了Sass给我们的范围。这里并没有使用CSSNano,所以我必须将文件保存在源目录中进行进一步的处理。当我们讨论可以使用的其他插件时,我们将重新讨论这个问题。
添加第二个插件
我们可以通过Sass的压缩格式来压缩CSS。如果想要压缩更多,那么需要使用CSS Nano插件来做进一步压缩。
要使用它,首先得先安装这个插件:
npm i -D cssnano
接下来需要修改构建脚本:
const cssnano = require('cssnano');
最后,我们需要修改任务,将CSS Nano合并到任务中来。我们通过向处理器数据组添加CSS Nano来实现这一点。修改后的任务如下:
gulp.task("processCSS", () => {
// What processors/plugins to use with PostCSS
const PROCESSORS = [
autoprefixer({browsers: ['last 3 versions']}),
ccssnano()
];
return gulp
.src("src/css/**/*.css")
.pipe($.sourcemaps.init())
.pipe(postcss(PROCESSORS))
.pipe($.sourcemaps.write("."))
.pipe(gulp.dest("src/css"))
.pipe($.size({
pretty: true,
title:
"processCSS"
}));
});
我们可以使用相同的方式添加更多的处理器:
- 安装需要的插件
- 将插件添加到处理器数组中
- 配置添加的插件
- 测试已添加的插件
根据上面的步骤以确保添加的插件能按照你的要求工作。
创建一个插件
我发现,PostCSS最吸引人的地方在于它的API,它可以让开发人员能够轻松地创建插件来满足特定的需求。
CSS代码会是什么样子
例如,假设我们有一组有关于营销方面的字体用于内容中。而不是在堆栈中输入所有的字体,你可以这样做:
html {
font-family: stack("Arial");
weight: normal;
style: normal;
}
编译后得到的CSS会像这样:
html {
font-family: 'Arial, "Helvetica Neue", Helvetica, sans-serif';
weight: normal;
style: normal;
}
配置项目
为了初始化插件项目,我们必须创建一个文件夹,并使用NPM初始化包,并自动接受默认值。我们可以用以下命令来做:
mkdir local-stacks # Creates the directory
cd local-stacks # Changes to the directory we just created
npm init --yes # Inits NPM accepting all defaults automatically
现在我们必须创建一个index.js
文件作为我们的插件入口点。我们可以这样做:
touch index.js
或者在文本编辑器中创建文件。我通常使用Visual Studio Code。
编写代码
为了能让插件运行,我们还需要安装两个插件:PostCSS引擎和Underscore,我们将用来合并本地和插件配置。我没有使用ES6模块导入语法(尽管它会让代码变得更简单),那是因为我想使用老版本的Node模块。
然后我们定义了我们想要使用的字体堆栈数组。我们想要用于堆栈的名称是key
,而堆栈本身就是value
:
const postcss = require('postcss');
const _ = require('underscore');
// Font stacks from http://www.cssfontstack.com/
const fontstacks_config = {
'Arial': 'Arial, 'Helvetica Neue', Helvetica, sans-serif',
'Times New Roman': 'TimesNewRoman, 'Times New Roman', Times, Baskerville, Georgia, serif',
'Lucida Grande':, 'Lucida Sans Unicode', 'Lucida Sans', Geneva, Verdana, sans-serif;
}
toTitleCase
会转换传递给它的字符串,这样每个单词的第一个字母就大写。我们用来获取字符串的正则表达式有点复杂(这是我第一次看到它的情况),所以我把它拆分了一下:
\w
匹配的是任何单个字符(相当于[a-zA-Z0-9_]
)\S*
匹配任何非空字符(相当于[^\r\n\t\f ]
)*
量词 —— 在零和无限次次数之间的匹配,尽可能多的返回g
修改器 —— 返回所有匹配项(第一次匹配后不返回)
代码如下:
// Credit for this function to http://bit.ly/1hJj9jb in SO
function toTitleCase(str) {
return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() +
txt.substr(1).toLowerCase();});
}
我们导出的模块是实际的插件。我们给它取了一个名local-stacks
,我们把它定认为函数。这个函数的功能具有:
- 我们在样式表中使用了
walkRules
的所有规则,这是PostCSS API的一部分 - 对于每一个规则,我们使用
walkDecls
遍历所有的声明,这也是PostCSS API的一部分 - 我们测试在声明中是否有一个
fontstack
调用:- 通过匹配括号内的值,然后替换任意的引号,得到所请求的
fontstack
的名称 - 如果用户没有指定,则使用结果字符串
- 在
fontstack_config
对象中查看字体堆栈的名称 - 获取在
fontstack
调用之前的字符串中的任何值 - 使用第一个字体和字体堆栈的值创建一个新字符串
- 将新值作为声明的值返回
- 通过匹配括号内的值,然后替换任意的引号,得到所请求的
代码如下:
module.exports = postcss.plugin('local-stacks', function (options) {
return function (css) {
options = options || {};
fontstacks_config = _.extend(fontstacks_config, options.fontstacks);
css.walkRules(function (rule) {
rule.walkDecls(function (decl, i) {
var value = decl.value
if (value.indexOf( 'fontstack(' ) !== -1) {
var fontstack_requested = value.match(/\(([^)]+)\)/)[1]
.replace(/["']/g, "");
fontstack_requested = toTitleCase(fontstack_requested);
var fontstack = fontstacks_config[fontstack_requested];
var first_font = value.substr(0, value.indexOf('fontstack('));
var new_value = first_font + fontstack;
decl.value = new_value;
}
});
});
});
}
});
下一步和结束
这是一个非常简单的插件。你可以看到Autoprefixer和 CSS Nano这样更复杂的例子以及你能用PostCSS做什么。如果你对PostCSS API感兴趣,可以在这里查看到详细的信息。
特别注意,你不必重新造轮子。在www.postcss.parts中有一个大型的插件生态系统。我们可以使用这些插件来得到我们想要的结果。 编写自己的插件很有趣,但并不要总是去做练习
一旦你确定了你的CSS项目,你就可以决定需要哪些PostCSS插件。
扩展阅读
- Post CSS Deep Dive
- Roll Your Own Preprocessor
- PostCSS Shortcuts and Shorthand
- PostCCSS Miscellaneous Goodies
- Create Your Own Plugin
- It’s time for everyone to learn about PostCSS
- Some Things You May Think About PostCSS And You Might Be Wrong
- A look into writing future CSS with PostCSS and cssnext
- Breaking up with Sass: it’s not you, it’s me
- Extending Sass with PostCSS
- How to Build Your Own CSS Preprocessor With PostCSS
- I’m Excited About PostCSS
- Improving the Quality of Your CSS with PostCSS
- PostCSS – Future of CSS after preprocessors
- PostCSS – Sass Killer or Preprocessing Pretender?
- Musings from Someone Discovering PostCSS
- So you want to make a PostCSS plugin
- That postcss. Its so hot right now
- Introduction to Postcss
- 7 Postcss Pluguins to Ease You Into Postcss
- So you want to make a PostCSS plugin
- Awesome PostCSS
- PostCSS深入学习
- PostCSS中文教程
**特别声明:**如查你想在自己的项目中使用PostCSS,但你又不想在互联网的大海中捞不同的PostCSS教程,你可以购买《深入PostCSS Web设计》一书。
本文根据@Carlos Araya的《PostCSS and crazy things you can do with it》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:https://publishing-project.rivendellweb.net/postcss-and-crazy-things-you-can-do-with-it/。
如需转载,烦请注明出处:https://www.fedev.cn/preprocessor/postcss-and-crazy-things-you-can-do-with-it.htmlnike air max 1 yellow