使用stylelint对CSS/Sass做代码审查
对样式审查?很少人会这么做吧,但实际上开发者应该有这样的态度,尤其是不同团队多人开发时,这一点尤为重要。
在本文中,我将陈述两点:一是为什么我们需要对样式进行审查,二是如何将审查工具融合到整体的构建流程中(适用于 CSS,也适用于 Sass)。
简介
什么是代码审查
代码审查是一个检查代码是否符合编程规范以及查找代码错误的过程,如果要做个比喻,那么它就是编程语言的拼写检查工具。代码审查可以帮助独立开发者更好的维护代码,但它更大的能力是帮助团队维护代码。
为什么我们需要审查样式
对样式进行审查的原因有很多,比如它可以维护代码的一致性,解析代码中的错误,减少冗余代码等等。
下面让我们看几个示例:
.no-space-after-colon {
display:block;
} ⬆
.no-semicolon {
position: relative ⬅
}
代码审查工具可以有效指出上述代码中的不规范之处。在审查工具中规定代码的规范写法虽然不是必要的,但这种做法有助于维护代码的一致性。此外,在团体开发中彼此不熟悉,如果我看到上述的代码会感到很恼火。
.invalid-hex {
color: #FFF00G;
} ⬆
代码审查工具也可以指出无效的颜色值,抛出一个类型错误。如果疏漏了这种错误,往往会导致页面上严重的视觉错误。
.unnecessary-prefixes {
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
}
随着浏览器的升级换代,有一些 CSS3 属性的浏览器前缀已经没有意义了。代码审查工具可以指出这些无意义前缀,此外,将它和 Autoprefixer 搭配起来,可以更加有效。
.duplicate-rule {
display: block;
transition: opacity .2s;
color: #444;
background-color: #eee;
transition: background-color .4s; ⬅
}
样式重复是一个常见的错误,就上面的代码而言,这里的 transition
值到底是 opacity
还是 background-color
呢?显而易见, background-color
会替代 opacity
。
代码审查是不是很有用呢?如果这还不够打动你,请继续阅读。
stylelint 简介
stylelint 是一个基于 Javascript 的代码审查工具,它易于扩展,支持最新的 CSS 语法,也理解类似 CSS 的语法。此外,因为它是基于 JavaScript,所以比起 Ruby 开发的 scss-lint 速度更快。
stylelint 是一个强大和现代的 CSS 审查工具,有助于开发者推行统一的代码规范,避免样式错误。
stylelint 由PostCSS 提供技术支持,所以它也可以理解 PostCSS 解析的语法,比如 SCSS。
PostCSS 是一个使用 JS 解析样式的插件集合,它可以用来审查 CSS 代码,也可以增强 CSS 的语法(比如变量和混合宏),还支持未来的 CSS 语法、行内图片等等。
PostCSS 的哲学是专注于处理一件事,并做到极致,目前它已经有了 200 多个插件,由于它们都是基于 JavaScript 编写的,所以运行速度非常快。
PostCSS 和 stylelint 就是我们接下来将要介绍的代码审查工具。
安装
stylelint 的强大之处就在于它非常灵活,无需花费过多的时间过滤各种规则,只需配置需要的规则即可完成 stylelint 的初始化。 stylelint 的配置文档 非常适用于初学者了解相关的审查规则。此外,他们还提供了一份 标准配置文件 用作参考。
在本文中,我将带领大家从一份更友好、简洁的配置开始。就我个人而言,我认为它比官方提供的配置文件更加灵活:
"rules": {
"block-no-empty": true,
"color-no-invalid-hex": true,
"declaration-colon-space-after": "always",
"declaration-colon-space-before": "never",
"function-comma-space-after": "always",
"function-url-quotes": "double",
"media-feature-colon-space-after": "always",
"media-feature-colon-space-before": "never",
"media-feature-name-no-vendor-prefix": true,
"max-empty-lines": 5,
"number-leading-zero": "never",
"number-no-trailing-zeros": true,
"property-no-vendor-prefix": true,
"rule-no-duplicate-properties": true,
"declaration-block-no-single-line": true,
"rule-trailing-semicolon": "always",
"selector-list-comma-space-before": "never",
"selector-list-comma-newline-after": "always",
"selector-no-id": true,
"string-quotes": "double",
"value-no-vendor-prefix": true
}
最后,建议读一下 stylelint 的官方配置文档 ,在其基础上做一些个性化的设置。接下来,让我们将这些审查规则融入到构建流程中。
如何审查 CSS
首先,让我们先来审查 CSS 代码。配置审查工具的过程非常简单,你只需要安装 gulp-postcss
/ postcss-reporter
和 stylelint
即可:
npm install gulp-postcss postcss-reporter stylelint --save-dev
接下来是 gulp 的配置文件 gulpfile.js
:
/**
* Linting CSS stylesheets with Stylelint
* http://www.creativenightly.com/2016/02/How-to-lint-your-css-with-stylelint/
*/
var gulp = require('gulp');
var postcss = require('gulp-postcss');
var reporter = require('postcss-reporter');
var stylelint = require('stylelint');
gulp.task("css-lint", function() {
// Stylelint config rules
var stylelintConfig = {
"rules": {
"block-no-empty": true,
"color-no-invalid-hex": true,
"declaration-colon-space-after": "always",
"declaration-colon-space-before": "never",
"function-comma-space-after": "always",
"function-url-quotes": "double",
"media-feature-colon-space-after": "always",
"media-feature-colon-space-before": "never",
"media-feature-name-no-vendor-prefix": true,
"max-empty-lines": 5,
"number-leading-zero": "never",
"number-no-trailing-zeros": true,
"property-no-vendor-prefix": true,
"rule-no-duplicate-properties": true,
"declaration-block-no-single-line": true,
"rule-trailing-semicolon": "always",
"selector-list-comma-space-before": "never",
"selector-list-comma-newline-after": "always",
"selector-no-id": true,
"string-quotes": "double",
"value-no-vendor-prefix": true
}
}
var processors = [
stylelint(stylelintConfig),
// Pretty reporting config
reporter({
clearMessages: true,
throwError: true
})
];
return gulp.src(
// Stylesheet source:
['app/assets/css/**/*.css',
// Ignore linting vendor assets:
// (Useful if you have bower components)
'!app/assets/css/vendor/**/*.css']
)
.pipe(postcss(processors));
});
上面短短五十行代码包含了审查规则和文件路径,请确保资源路径与上面的代码相匹配。
更令人惊奇的是,只需改动一小段代码就可以同时支持 Sass,让我们来修改一下吧。
如何审查 Sass
使用 PostCSS 审查 Sass 代码非常简单,与审查 CSS 代码唯一不同的地方就在于,你需要让 PostCSS 识别 .scss
语法。这一问题可以通过安装 postcss-scss
插件来完成,安装插件后,修改一下配置文件:
npm install postcss-scss --save-dev
修改配置文件:
//[...]
return gulp.src(
['app/assets/css/**/*.css',
'!app/assets/css/vendor/**/*.css']
)
.pipe(postcss(processors), {syntax: syntax_scss}); ⬅
});
以上就是 gulp 配置文件的全部内容了。总结起来,你需要安装以下工具:
npm install gulp-postcss postcss-reporter stylelint postcss-scss --save-dev
/**
* Linting Sass stylesheets with Stylelint
* http://www.creativenightly.com/2016/02/How-to-lint-your-css-with-stylelint/
*/
var gulp = require('gulp');
var postcss = require('gulp-postcss');
var reporter = require('postcss-reporter');
var syntax_scss = require('postcss-scss');
var stylelint = require('stylelint');
gulp.task("scss-lint", function() {
// Stylelint config rules
var stylelintConfig = {
"rules": {
"block-no-empty": true,
"color-no-invalid-hex": true,
"declaration-colon-space-after": "always",
"declaration-colon-space-before": "never",
"function-comma-space-after": "always",
"function-url-quotes": "double",
"media-feature-colon-space-after": "always",
"media-feature-colon-space-before": "never",
"media-feature-name-no-vendor-prefix": true,
"max-empty-lines": 5,
"number-leading-zero": "never",
"number-no-trailing-zeros": true,
"property-no-vendor-prefix": true,
"rule-no-duplicate-properties": true,
"declaration-block-no-single-line": true,
"rule-trailing-semicolon": "always",
"selector-list-comma-space-before": "never",
"selector-list-comma-newline-after": "always",
"selector-no-id": true,
"string-quotes": "double",
"value-no-vendor-prefix": true
}
}
var processors = [
stylelint(stylelintConfig),
reporter({
clearMessages: true,
throwError: true
})
];
return gulp.src(
['app/assets/css/**/*.css',
// Ignore linting vendor assets
// Useful if you have bower components
'!app/assets/css/vendor/**/*.css']
)
.pipe(postcss(processors), {syntax: syntax_scss});
});
如果你想了解如何使用插件扩展 stylelint,那么就请继续阅读后续内容
扩展 stylelint
和 PostCSS 一样,Stylelint 也可以通过插件进行扩展。接下来让我们通过一些实例学习如何使用审查工具改善代码的可读性和可维护性。
实战演练
话说有个产品经理新接了个 web app 的活,项目正处于紧张的开发中,为了减少一些开发时间,他决定增加一个特性来替代之前的一揽子方案,这个特性是这样的:给组件本身添加一个鼠标悬停时的 box-shadow 效果,同时给组件的内部的链接增加一个鼠标悬停样式。
下面是这个产品经理增加的代码段:
.component {
position: relative;
//[...]
&:hover { ⬅
box-shadow: 1px 1px 5px 0px rgba(0,0,0,0.75);
.component__child { ⬅
ul { ⬅
li { ⬅
a { ⬅
&:hover { ⬅
text-decoration: underline;
}
}
}
}
}
}
}
真是惨不忍睹!
选择器嵌套是 Sass 最容易被误用的特性,合理使用它可以提高开发效率,滥用则会毁掉整个项目。嵌套往往是由偷懒引起的,这些代码往往难以阅读。上面的 &:hover{...}
的嵌套层级太深,很容易混淆其他开发者对这段代码的理解。最重要的是,这段嵌套在这里完全是没有必要的。
这就是上面的嵌套代码编译生成的 CSS:
.component:hover .component_child ul li a:hover {}
/* What the heck is this?! */
如果后续接手项目的开发者想要覆盖这段级联样式,那真是大工程。所以有一点值得牢记,那就是除非你非常确定嵌套是必要的,否则不要使用它。
幸运的是,我们有插件来阻止这种情况的发生!我们可以安装 stylelint-statement-max-nesting-depth
插件,设置最大嵌套层级来避免过渡嵌套的现象:
npm install stylelint-statement-max-nesting-depth --save-dev
在 gulp 的排位置文件中增加 scss-lint
相关的任务信息:
gulp.task("scss-lint", function() {
var stylelintConfig = {
"plugins": [
"stylelint-statement-max-nesting-depth"
],
"rules": {
//[...]
"statement-max-nesting-depth": [3, { countAtRules: false }],
}
}
//[..]
});
为了增强团队的共建意识,我在这里将 limit
设置为了 3
。由于有嵌套层级的限制,所以产品经理就会来自 stylelint 的重构提示。产品经理没怎么细想,就改成了下面这样:
.component:hover {
box-shadow: 1px 1px 5px 0px rgba(0, 0, 0, 0.75);
.component__child {
ul {
li {
a:hover {
text-decoration: underline;
}
}
}
}
}
这个重构之后的版本看起来可读性好多了,但仍然有不少缺陷。事实上,上面代码中的嵌套是完全没有必要的。stylelint 可以检测出这一点,并会强制产品经理重新思考样式代码。
.component:hover {
box-shadow: 1px 1px 5px 0px rgba(0, 0, 0, 0.75);
}
.component__child {
a:hover {
text-decoration: underline;
}
}
现在,代码更加健壮了!stylelint 已经接受了代码,不会再提出异议了。虽然上面的代码没有问题,但我们其实可以做的更好。如果你希望严格要求团队的每一个成员,那么可以禁用嵌套,这会让团队成员,包括产品经理,更加严谨地编写代码。
.component:hover {
box-shadow: 1px 1px 5px 0px rgba(0, 0, 0, 0.75);
}
.component__link:hover {
text-decoration: underline;
}
通过以上介绍和实战演练,希望我已经说服了你:样式审查是非常值得投入的一项流程。代码审查应该成为我们的朋友,只需投入一点时间,就可以收获代码整体的可读性、可维护性。
本文根据 @Scotty Vernon 的《 How to lint your Sass/CSS properly with Stylelint 》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处: http://www.creativenightly.com/2016/02/How-to-lint-your-css-with-stylelint/ 。
使用stylelint对CSS/Sass做代码审查的更多相关文章
- Google是如何做代码审查的?
Google是一个非常优秀的公司.他们做出了很多令人称赞的东西—既是公司外部,人们可以看到的东西,也是公司内部.有一些在公司内部并不属于保密的事情,在外部并没有给予足够广泛的讨论.这就是我今天要说的. ...
- 谷歌是如何做代码审查的 | 外刊IT评论 - Google Chrome
谷歌是如何做代码审查的 本文的作者 Mark CC 在上一篇文章中提到过,我已经不在Google工作了.我还没有想清楚应该去哪里-有两三个非常好的工作机会摆在我面前.因为在这段做决 ...
- 运用HTML5+CSS3和CSS滤镜做的精美的登录界面
原始出处http://chenjinfei.blog.51cto.com/2965201/774865 <!DOCTYPE HTML> <html> <head> ...
- CSS & SASS & SCSS & less
CSS & SASS & SCSS & less less vs scss https://github.com/vecerek/less2sass/wiki/Less-vs. ...
- 【CSS】333- 使用CSS自定义属性做一个前端加载骨架
点击上方"前端自习课"关注,学习起来~ 我们在打开APP或者网站的时候,经常可以看到这样的效果,在内容加载完成之前,会有一个骨架动画的出现,这种加载方式比传统的进度条方式要友好的多 ...
- CSS样式做圆角
我处理圆角的版本是由内置的绝对定位的四个div组成,每个div都有唯一的圆角图片作CSS Sprite操作.我们将会这样做: 是什么方式导致这项技术表现得这么了不起呢(What makes this ...
- vue2.0 样式表引入的方法 css sass less
在引入样式之前,首先要了解static.assets两个文件夹的区别. 从字面上可以看出,static用来存放静态文件,assets用来存放资源文件: static存放的文件不会被编译,打包后直接赋值 ...
- CSS, Sass, SCSS 关系
Sass(Syntactically Awesome Style Sheets) ,是一种css预处理器和一种语言, 它可以用来定义一套新的语法规则和函数,以加强和提升CSS. 它有很多很好的特性,但 ...
- 用html+css+js做打地鼠小游戏
html 代码 first.html <!DOCTYPE html> <html lang="en"> <head> <meta char ...
随机推荐
- 企业级应用架构模式N-Tier多层架构
先来看经典的3层架构,看下图: 涉及到平台可以是: Ruby on Rails, Java EE, ASP.NET, PHP, ColdFusion, Perl, Python 层 ...
- SQLServer修改表字段名称
EXEC sp_rename 'TableName.[ColumnName]','ColumnNew','COLUMN'
- 怎样给div增加resize事件
当浏览器窗口被调整到一个新的高度或宽度时,就会触发resize事件,这个事件在window上面触发,那么如何给div元素增加resize事件,监听div的高度或宽度的改变呢? 先来回答另一个问题,监听 ...
- Javascript9张思维导图
1.变量 2.运算符 3.数组 4.流程语句 5.字符串函数 6.函数基础 7.DOM操作 8.BOM 9.正则表达式
- VBA常用代码解析
031 删除工作表中的空行 如果需要删除工作表中所有的空行,可以使用下面的代码. Sub DelBlankRow() DimrRow As Long DimLRow As Long Dimi As L ...
- 【极品代码】一般人我不告诉他,手机端h5播放时不自动全屏代码
已测适用于ios,某些安卓手机微信下播放视频会出现播放器控件(这个实在是无力吐槽噢,因为之前还遇到过微信播放完视频后竟然无法退出全屏出现广告的情况,只有播放完后刷新页面并且要放到框架页里才能屏蔽微信视 ...
- gitflow以及git
git大概只会用常用的那几个命令,自己用的最多的也只是add commit push pull之类的,然后那天电话面试问我版本回退怎么办我都忘记了. 然后又看了看教程,此时想起来做项目的时候师兄说的g ...
- java中使用javamail发送邮件
1. 电子邮件协议 电子邮件的在网络中传输和网页一样需要遵从特定的协议,常用的电子邮件协议包括 SMTP,POP3,IMAP. 其中邮件的创建和发送只需要用到 SMTP协议,所有本文也只会涉及到SMT ...
- pptpvpn 连接后 无法上外网
VPN拨号后只能连内网,不能上外网的原因和解决方法 因为众所周知的原因,很多个人或者单位需要架设自己的VPN.会遇到一些奇怪的情况,比如说:为什么连上单位的VPN后就只好上公司的内网(局域网),外网( ...
- SQL必知必会 14-22(完)
博主依然不想打字,又向你仍来了一堆代码... 13(续) 在SELECT中用COUNT()以及联合 mysql> SELECT customers.cust_id,COUNT(orders.or ...