当我们提及预编译的时候,我经常会被问到的一个问题是Mixins
还是 @extend
? 关于这个话题我经常直言不讳,而且鉴于以下的这几条原因,我坚定的认为你应该避免使用@extend
:
@extend
会改变了你的源命令,这在CSS中是相当危险的。@extend
会破坏代码结构合理性,把不相关的选择器串联到一起。@extend
是非常贪婪的,它会包含一切的代码,而不仅仅是你想要的那一个。@extend
可能会很快就脱离我们控制。
@extend
现在被广泛的认为是一种反面模式, 所以它的使用慢慢淡出了人们的视野,但是我们还没有完全弃用它。
我昨天和一个客户聊天的的时候被问到mixin
和@extend
哪个更好,我告诉他了我通常会使用的答案:**永远不要使用@extend
**,但却被反问了到:“@extend
不是性能更好吗?它生成了更少的代码”
认为使用@extend
(当被正确的使用)生成更少的CSS是正确的,但是对于性能而言我的回答是错:mixins
的性能更好。
我相当有自信的回答了这个的问题,尽管我从没做过任何的测试。我很有自信的原因是我有一套独门秘笈:
由于gzip
是有利于重复代码压缩的,很显然如果我们能明确的告知压缩程序我们重复的声明,我们就能到一个更好的压缩比例。
你看,当人们谈论 mixins
的性能的时候,他们通常考虑的是文件在服务器上的大小。但是由于有gzip
的存在(你也使用gzip
的对吧?),我们应该思考网络传输过程中的文件大小。
我的想法是一旦我们使用gzip
压缩我们的CSS,包含重复字符串次数较多的文件会变得比重复字符串次数小的文件更小,所以不要考虑文件在服务器的文件系统中的大小。所以我假设如果一个文件包含重复的字符串,经过gzip
压缩会变得更小。
我决定回到我的酒店把我的理论验证一下。
实验
这就是我实验的:
我新建了两个CSS文件每个文件文件有1000
个用Sass生成的独一无二的类:
@for $i from 1 through 1000 {
.#{unique-id()}-#{$i} {
...
}
}
我给每个类声明了独一无二的内容,通过重复使用父级的选择器生成每项自身的类名,我还在里面生成了一些没有意义的字符串:
@for $i from 1 through 1000 {
.#{unique-id()}-#{$i} {
content: "ibf#{&}jaslbw";
}
}
我选择了三个简单的声明应用于所有的个类:
color: red;
font-weight: bold;
line-height: 2;
在一个文件中,我使用mixin
来进行声明:
@mixin foo {
color: red;
font-weight: bold;
line-height: 2;
}
.#{unique-id()}-#{$i} {
@include foo;
content: "ibf#{&}jaslbw";
}
在另一个文件中,我使用@extend
来进行声明:
%foo {
color: red;
font-weight: bold;
line-height: 2;
}
.#{unique-id()}-#{$i} {
@extend %foo;
content: "ibf#{&}jaslbw";
}
所有的例子都可以在github上看到。
在这个测试中,这两个文件分别用两种方式各自生成了1000
个独一无二的声明和三个相同的属性语句。
他们的大小可能你并不吃惊:
mixin.css
文件的大小108K
extend.css
文件的大小是72K
- 两个文件之间相差了
36K
- 使用
mixins
比使用@extend
大了150%
这恰好就是我所预料的那样:** mixins
会比@extend
产生更多的CSS代码**。
但是!我们必须瑾记我们不用担心文件在服务器文件系统中大小,我们仅仅需要关心gzip
压缩后的文件大小。
mixin.css
经过gzip
后得到的大小是12K
extend.css
经过gzip
后得到的大小是18K
- 两个文件之间相差了
6K
- 使用
mixins
比使用@extend
小了33.333%
太令人吃惊了! 在我们经过Sass编译得到的文件中,使用 mixins
的文件比使用 @extend
的文件大了150%
,但是经过gzip
压缩后,使用 mixins
的文件反而比使用 @extend
的文件小了 33.333%
。我的理论是正确的!
实验
我个人觉得上面的测试非常的公正,创建独一无二的类名是为了阻碍压缩,所以我们可以很精确的测试gzip
在我们现实项目中的作用:压缩共享的声明。
但有人说上面的测试文件非常的不贴近现实,所以我决定直接拿一个已有的项目测试。
我用了一个现有项目当中的CSS文件,并且把CSS文件做了一份拷贝,然后我分别用@import
导入我的两个测试文件到各自的项目中。这意味着我的测试声明被 1794
行现有项目的中的代码包围着。
我编译并且压缩了两个测试的文件,这是他们的结果:
mixin.css
的结果是16K
extend.css
的结果是22K
- 两个文件之间相差了
6K
- 使用
mixins
比使用@extend
小了27%
绝对意义上来考虑结果似乎相差不大(仅仅6K
),但是相对而言,我们仅通过选择使用mixins
来声明重复的代码就能节省27%
的流量!
Mixins 的性能更好
我的测试得出了一个非常可靠的结论:minxins
在网络传输中比@extend
拥有更好的性能.尽管有些文件未压缩时更大,但使用gzip
压缩后,依然可以保证我们拥有更好的性能。
关于 @extend
的性能之争从此不复存在,@extend
除了会对你的CSS结构产生破坏之外同样在性能上也同样落后,所以请停止使用它,一起拥抱mixins
吧!
本文根据@csswizardry的《Mixins Better for Performance》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://csswizardry.com/2016/02/mixins-better-for-performance
如需转载,烦请注明出处:http://www.w3cplus.com/preprocessor/mixins-better-for-performance.html