Facebook:CSS 的质量提升与展望

与成千上万的facebook工程师在这纷繁复杂的产品线中相互协作, 代码质量通常面临独特的挑战。

我们不仅需要处理庞大的数据库, 还需要跟上时代发展的节奏 —— 新增功能的上线、 已有功能的改善, 甚至是产品重组的需要。

对于CSS来说,这意味着成千上万的文件在一个不断变化的状态中。

即使我们已经尽力通过代码回顾、风格指导,甚至是重构等方式去确保css代码的质量,然而无意的小错误依然可以让我们措手不及。

直到最近,我们使用的还是一款我们自主开发的CSS检测器(CSS linter)去获取一些基本的错误以保障代码风格的一致。尽管它已经达到了我们的目的,但我们需要的是更强大的解决方案。

正则是远远不够的

旧的css检测器基本上是一些正则表达式搜索和替换规则。正确解析CSS不是一个简单的问题,和供应商扩展和定制规格的变化,会计是更具挑战性。

下面是一个旧代码的例子:

preg_match_all(
    // 这条规则匹配的是没有前置选择器的属性选择器
    '/\/\.?\\/|\{[^}]\}|\s(\[[^\]]+\])/s',
    $data,
    $matches,,k
    PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
    foreach  ($matches as $match)  {
        if (isset($match[1])) {
            raiseError(...);
        }

维护这种神秘的匹配规则维护是极其无趣的。且不说它很难改变和理解,性能也是一个问题。对于每个规则来说,我们不得不一遍又一遍的去遍历整个输入,匹配不同的正则表达式。

抽象语法树

我们决定新的解决方案是基于一个真实的,遵循规范的CSS解析器。 由于代码必须对这种类型的语法有效解析器工作,我们不能再把我们整个CSS代码库作为一个巨大的文本。 这种新方法将显著改善CSS代码质量打字错误,否则他们就会被忽视,导致默默地进行不正确的视图呈现或行为。

什么样的行为呢?

一些潜伏在我们巨大代码库阴影中的代码可能向下面一样:

{
    display: none;
    background-color: #8B1D3;
    padding: 10px,10px,0,0;
    opacity: 1.0f;}

你能发现细微的差别吗? 属性名输入错误,不正确的十六进制,错误的分隔符——浏览器会忽略这些,这是与我们开发人员的意图相去甚远。

它意识到没多久 PostCSS 将是一个伟大的工作,一个合适的工具,基于标准的CSS解析器与一个优秀的模块化的体系结构。 然后,我们选择 Stylelint 作为我们的CSS检测器。 它基于PostCSS,非常灵活,并且有很好的支持。
类似于基于javascript解析器/过滤器的Esprima 和 ESLint,PostCSS Stylelint给你访问整个AST(抽象语法树)的权限。 AST节点可以方便地使用任何条件去访问任何节点:我们使用正确的类名了吗? 我们包括正确的抽象了吗? 有弃用或不受支持的扩展吗? 有本地化问题吗?

在下面这个例子中,我们将遍历所有的声明,并找到所有的首字母大写("text-transform: uppercase")的片段。

root.walkDecls(node =>  {
    if (node.prop === 'text-transform' && node.value === 'uppercase') {
        report({  ...  });
    }});

我们甚至可以解析和解构低级的函数例如linear-gradient。 这里有一个更复杂的例子:找到linear-gradient函数,并检查它的第一个参数。

// disallow things like linear-gradient(top, blue, green) w. incorrect first valueroot.walkDecls(node => {
    const parsedValue = styleParser(node.value);
    parsedValue.walk(valueNode => {
        if (valueNode.type === 'function' && valueNode.value === 'linear-gradient') {
            const firstValueInGradient = styleParser.stringify(valueNode.nodes[0]);
            if (disallowedFirstValuesInGradient.indexOf(firstValueInGradient) > -1) {
                report({  ...  });
            }
        }
    });});

所有无论这些CSS代码如何格式化,如何规则、声明和如何绑定,都非常容易理解和更新。

我们可以非常欣喜的看到,通过使用PostCSS and Stylelint,当我们处理起例如纠正错别字、关键帧数、!important、复杂选择器、非标准属性等任何常见及潜在问题时都变得得心应手起来~

自定义规则

我们可以通过一个非常便利的内部插件机制(built-in plugin mechanism)来自定义我们的规则。 我们现有的插件如下:

slow-css-properties to warn against performance-sensitive properties like opacity or box-shadow (just to be mindful of them)

filters-with-svg-files to warn against filters not being supported in Edge when referencing SVG files

use-variables to warn against values that could be replaced with existing constants (we use customvar(...) abstraction)

common-properties-whitelist to catch potentially nonexistent properties (i.e., typos)

mobile-flexbox to catch multi-value flex that's not supported in older mobile browsers

text-transform-uppercase to warn against "text-transform: uppercase" (which is not internationalization-friendly)

我们为这些Stylelint插件制定了很多和 规则 和 附属条例,试图将它们释放给某个独立的仓库或者是某个线程的Stylelint团队。

自动替换

我们的静态分析过程的一个非常重要方面是自动格式化。 linter支持修补,如果不一致时,它会询问你是否需要根据规则进行替换。 这可能是一个强大和节省时间的概念。 提交时你想要做的最后一件事是看到检测错误,然后回去修复它们,尤其当此项工作是非常平常的工作,比如字母重新排序规则。通常更好的做法是让一个自动格式化的工具去完成其工作,以节省开发时间。

不幸的是,Stylelint没有内置的自动格式化(可以说,linter不应该关心这样一个任务),所以我们必须重新添加及实现的一些现有Stylelint规则去提升我们对基础设施的支持。同时,我们正在开发一种潜在的,在未来可以为所有用户服务的通用Stylelint。

测试所有的事情

我们的老版的CSS检测器问题之一是,我们没有单元测试。 这是一个至关重要的事情,因为我们需要对任意的文本进行解析。 在使用Stylelint重写我们的检测器,我们添加了测试每一个规则,确保规则可以获取正确的东西,忽略了无关紧要的东西,并建议合适的替代品。

我们使用一个可信的且易于理解的Jest框架 ,测试起来是这样的:

test.ok('div { background-image: linear-gradient( 0deg, blue, green 40%, red ); }',
    'linear gradient with valid syntax');test.notOk('a { background: linear-gradient(top, blue, green); }',
    message,
    'linear-gradient with invalid syntax');

接下来是什么

这个高质量的CSS重写只是第一步。 有很多有用的规则我们计划添加(内置和自定义的)——所有这些旨在抓住常见错误,执行最佳实践和控制代码风格惯例。 我们已经使用JavaScript(通过ESLint)所以我们没有理由不应该用它去处理CSS。

目前检测器已经与Phabricator集成,成为了我们的代码协作工具,所有的的警告/建议都在修订当中。

这使得CSS检测器在工作流中迈进了非常大的一步。

有一个合适的CSS解析器的另一大好处是,它可以收集有关代码库的准确的统计数据。 最近使用的属性/值是什么? 也许他们应该删除或替换(通过电线发送更少的字节)。 最流行的颜色/字体大小/ 层级是什么? 也许他们应该被抽象成可重用的组件或变量。 “最重”选择器是什么? 这里也许有一个性能问题等。

所有的这些可以帮助它提高性能和维护。

关于react和内联样式?

值得一提的是CSS-in-JS概念 在react社区逐渐流行起来。 现在的情况是,一个CSS检测器的情况在很大程度上还是作为一个无关紧要的css文件检测器。它目前旨在解析传统CSS文件,以后可能渐渐的去适应解析在JS中定义为CSS代码段。不过,通过PostCSS的JS API,处理起这些来应该是相当简单的。

虽然我们正在Facebook中积极探索CSS-in-JS的方法,它还处在早期的实验阶段,我们仍然有很大的CSS代码库维护。

共同合作

我们很高兴使用开源工具,并尽可能多得到的反馈。衷心希望它可以提供一个坚实的现代规则和准则,让每个人去使用和相互合作。

谢谢JS infra和webspeed团队,和任何一个帮助重写的朋友,Stylelint 的 David Clark和Richard Hallows。以及使postcss这种神奇的工具成为可能的整个社区。

文章转载自 开源中国社区[http://www.oschina.net]

时间: 2024-09-19 09:18:02

Facebook:CSS 的质量提升与展望的相关文章

Facebook 使用 Stylelint 以保证 CSS 代码质量

近日,来自Facebook的开发者Juriy Zaytsev发布文章称,他们更换了CSS Linter工具,采用了基于PostCSS的 lint作为新的Linter工具,以期保证CSS代码质量. 上千名工程师,多条不同产品线,庞大代码库,日渐增加的新特性--种种特点加在一起,给Facebook的代码质量管理带来了独特的挑战.而如何保证上千份不停变换的CSS文件质量,对于Facebook来说,也是非常头疼的问题.Facebook为了解决这个问题,采用了Code Review.代码样式规范.重构以及

Facebook使用Stylelint以期保证CSS代码质量

近日,来自Facebook的开发者Juriy Zaytsev发布文章称,他们更换了CSS Linter工具,采用了基于PostCSS的Stylelint作为新的Linter工具,以期保证CSS代码质量. 上千名工程师,多条不同产品线,庞大代码库,日渐增加的新特性--种种特点加在一起,给Facebook的代码质量管理带来了独特的挑战.而如何保证上千份不停变换的CSS文件质量,对于Facebook来说,也是非常头疼的问题.Facebook为了解决这个问题,采用了Code Review.代码样式规范.

Facebook对memcached的提升

如果你翻阅过一些关于大型网站扩展(Scaling)的资料,那么你可能听说过一个叫memcached的东西.memcached是一个高性能.分布式的内存对象缓存系统.我们Facebook可能是世界上最大的memcached用户了.我们利用memcached来减轻数据库的负担.memcached确实很快,但是我们还要让他更快.更高效.我们使用了超过800台服务器,提供超过28TB的内存来服务于用户.在过去的一年里,随着Facebook的用户量直线上升,我们遇到了一系列的扩展问题.日益增长的需求使得我

盒子端 CSS 动画性能提升研究

不同于传统的 PC Web 或者是移动 WEB,在腾讯视频客厅盒子端,接大屏显示器(电视)下,许多能流畅运行于 PC 端.移动端的 Web 动画,受限于硬件水平,在盒子端的表现的往往不尽如人意. 基于此,对于 Web 动画的性能问题,仅仅停留在感觉已经优化的OK之上,是不够的,想要在盒子端跑出高性能接近 60 FPS 的流畅动画,就必须要刨根问底,深挖每一处可以提升的方法.   流畅动画的标准 理论上说,FPS 越高,动画会越流畅,目前大多数设备的屏幕刷新率为 60 次/秒,所以通常来讲 FPS

2016光伏:追求质量 提升效益

虽然说刚刚过去的2015年少数设备制造企业仍未完全脱困,虽然说这一年中一些地区的弃光问题仍然存在,但在翻过2015年的最后一页之后,整个行业还是在这个冬天里透出了更多的暖意. 这股暖意会在2016年的春天来临前如何延续?在刚刚召开的2016全国能源工作会议上,"大幅度增加非化石能源消费比重"."大力发展非化石能源"等振奋整个太阳能发电行业的话语一再被提及,也让人们对"十三五"的开局之年充满希冀. 光伏新增装机超1500万千瓦 "十二五&

大数据为医疗质量提升带来更多可能性

ZDNET至顶网CIO与应用频道 07月11日 评论分析(文/丁慧茹): "现在医院对于当下很流行的大数据技术经常呈现两种极端,要么盲目地趋之若鹜,要么认为离自己还太遥远."这是记者日前采访国内某三甲医院的CIO时听到的一句话. 其实,医院呈现这样的态度,是个很正常的反应.一方面,无论是政策督导还是医院本身的策略,都急切地希望快速提升医疗服务质量,大数据就成了"理所当然"的选择了:另一方面,医院所有努力和一切提升围绕的根本是医疗水平,而医患关系的紧张,又会让医院谨慎

衢州市借力大数据技术 助推薄弱学校教育质量提升

一是基于大数据的学业诊断,发现学生问题.明确提升方向.衢州市选择了柯城书院中学.柯城白云学校.衢州高级中学.常山城南中学.龙游凯马国际学校等近20所城乡薄弱学校进行试点,从作业评价做起,包括考试评价,基于双向细目表的大数据的学业诊断,通过数据挖掘呈现出学生各科知识点的缺陷,为学生的查漏补缺和教师的后续教学提供精准的依据和目标,提升教师的教.学生的学.书院中学2016年初中学业水平考试的排名从两区的23位跃升到14位.龙游凯马国际学校在全县高一期末统测中的成绩比对中考录取分数,平均每位学生进步15

阿里云在线教育解决方案——促进教育资源均等化,助推教育质量提升

摘要:本文的整理自2017云栖大会-南京峰会上阿里云教育事业部首席架构师石立勇的分享讲义,讲义主要介绍了当前国内在线教育的发展情况和需要面对的挑战,并分享了阿里云作为在线教育行业专业合作伙伴所具有的优势,并且详细地介绍了阿里云在线教育解决方案以及诸多优点. 在2017云栖大会-南京峰会上,阿里云教育事业部首席架构师石立勇(花名:用奇) 做了题为<阿里云在线教育解决方案 >的分享.目前国内在线教育行业主流已经演化到移动互联时代,部分业务已经步入大数据时代.而在线教育从业者需要更加关注用户.关注业

通过css和jQuery实现facebook底部的管理面板

近几年社交性网站变的越来越火,facebook在社交网站里面排名是靠前的.facebook里面有很多Ajax做的特效和功能给人深刻的印象.它底部的管理面板是我尤其喜欢的一个.它几乎将使用最多的功能链接都展现.组织在这里.这周我将通过第一部分介绍如何通过css和jQuery实现facebook底部的管理面板效果.part 1 演示 最终演示 第一部分:结构和信息提示框--html&css管理面板的结构使用无序列表ul创建.最后两个li列表(Alert Panel & Chat Panel)将