重构 CSS:简介(第 1 部分)

已发表: 2022-03-10
快速总结 ↬ CSS 重构不是一件容易的事——它需要以一种不会产生问题的方式来完成。 首先,我们需要分析现有的代码库,审核 CSS 代码库的健康状况,发现弱点,就方法达成一致,并说服管理层在流程中投入时间和资源。

CSS 是一种简单的样式表语言,用于定义网站或文档的呈现方式。 然而,这种简单性为许多潜在问题和技术债务敞开了大门——臃肿的代码、特异性地狱、几乎没有区别的重复代码块、剩余的未使用选择器、不必要的黑客攻击和变通方法等等。

这种技术债务如果不按时偿还,可能会累积并导致严重的问题。 最常见的是,当添加新的 UI 组件并使代码库难以维护时,它可能会导致意想不到的副作用。 您之前可能参与过一个 CSS 代码库很差的项目,并考虑过如何以不同的方式编写代码,从而有机会从头开始重构或重写所有内容。

无论如何,重构大部分 CSS 代码都不是一件容易的事。 有时,这似乎只是“删除质量差的代码,编写更好的 CSS,并部署闪亮的改进代码”的情况。 但是,还有许多其他因素需要考虑,例如重构实时代码库的难度、预期持续时间和团队利用率、确定重构目标、跟踪重构效果和进度等。还有说服管理层或项目利益相关者的问题将时间和资源投入到重构过程中。

在这个由三部分组成的系列中,我们将从头到尾介绍 CSS 重构过程,首先了解如何处理它以及重构的一些一般优缺点,然后再讨论重构策略本身并结束有一些关于 CSS 文件大小和性能的一般最佳实践。

部分:CSS 重构

  • 第 1 部分: CSS 重构:简介
  • 第 2 部分:CSS 重构:策略、回归测试和维护
  • 第 3 部分:CSS 重构:优化大小和性能
  • 订阅我们的电子邮件通讯,不要错过下一个。

劣质 CSS 的副作用

尽管 CSS 具有灵活性和简单性,但它本身存在一些基本问题,这些问题首先允许开发人员编写低质量的代码。 这些问题源于它的特殊性和继承机制,在全局范围内运行,源顺序依赖等。

在团队层面,大多数 CSS 代码库问题通常源于不同的技能水平和 CSS 知识、不同的偏好和代码风格、对项目结构和现有代码和组件缺乏了解、缺乏项目层面或团队级标准和指南等。

因此,质量差的 CSS 可能会导致超出简单视觉错误的问题,并可能产生各种严重的副作用,从而影响整个项目。 一些这样的例子包括:

  • 由于开发团队中不同的 CSS 技能水平以及缺乏内部规则、约定和最佳实践,随着更多功能的添加而降低代码质量
  • 添加新功能或扩展现有选择器会导致代码的其他部分出现错误和意外副作用(也称为回归)。
  • 具有重复代码块或 CSS 代码块的多个不同 CSS 选择器可以分离成一个新的选择器并通过变化进行扩展。
  • 来自已删除功能的剩余、未使用的代码块。 开发团队已经不知道使用了哪些 CSS 代码,哪些可以安全删除。
  • 文件结构、CSS 类命名、CSS 整体质量等方面的不一致
  • “特殊性地狱”,通过覆盖而不是现有的 CSS 代码库来添加新功能。
  • 撤消高特异性选择器“重置”低特异性选择器样式的 CSS 。 开发人员正在编写更多代码以减少样式。 这会导致代码冗余和大量浪费。
跨多个选择器(没有媒体查询或伪类)有很多划掉的样式(在浏览器样式检查器中)可能是由于结构不良的 CSS 导致的撤消 CSS 的指示。 这些 CSS 类被少数其他没有媒体查询和伪类的类覆盖,导致更多的代码来实现更少的样式。 (大预览)

在最坏的情况下,所有上述问题结合起来可能会导致CSS 文件过大,即使应用了 CSS 缩小。 这个 CSS 通常是渲染阻塞的,所以浏览器在完成下载和解析 CSS 文件之前甚至不会渲染网站内容,导致在较慢或不可靠的网络上的用户体验和性能很差。

这些问题不仅会影响最终用户,还会影响开发团队和项目利益相关者,使维护和功能开发变得困难、耗时且成本高昂。 这是在争论 CSS 重构或重写时提出的更有用的论点之一。

我最近审核了一个网站,该网站加载了一个 2.2MB 的缩小 CSS 代码文件。 像这样异常大的文件可能是 CSS 代码需要重构甚至从头开始重写的潜在指标。 (大预览)

Netlify 的团队指出,他们大规模的 CSS 重构项目背后的原因是,随着项目的复杂性和添加的 UI 组件越来越多,代码质量和可维护性不断下降。 他们还注意到,随着越来越多的人使用 CSS 代码库,缺乏内部 CSS 标准和文档导致代码质量下降。

“(……)从有组织的 PostCSS 开始逐渐发展成为一个复杂且纠缠不清的全球 CSS 架构,具有许多特殊性和覆盖性。 正如您所料,它引入的额外技术债务使得在不增加任何回归的情况下难以保持快速发货。 此外,随着贡献代码库的前端开发人员数量也在增长,这种 CSS 架构变得更加难以使用。”
跳跃后更多! 继续往下看↓

重构还是重写?

重构允许开发人员在不改变其表现形式或核心功能的情况下,逐步并有策略地改进现有代码库。 这些改进通常范围较小且有限,不会引入破坏性的、广泛的架构更改或向现有代码库添加新的行为、特性或功能。

例如,当前的代码库具有卡片组件的两种变体——第一种是由经验丰富的开发人员在项目开发早期实现的,第二种是在项目启动后由经验不足的开发人员在很短的期限内添加的,所以它具有重复的代码和具有高特异性的广泛选择器。

需要添加第三个卡片变体,它与其他两个卡片变体共享一些样式。 因此,为了避免错误、重复代码和复杂的 CSS 类以及 HTML 标记,团队决定在实现新的变体之前重构卡片组件 CSS。

重写允许开发人员对代码库进行重大更改,并假设当前代码库中的大多数(如果不是全部)代码都将被更改或替换。 重写允许开发人员从头开始构建新的代码库,解决当前代码库中无法修复或修复成本高的核心问题,改进技术堆栈和架构,并为新代码库建立新的内部规则和最佳实践。

例如,客户正在进行品牌重塑,需要使用新设计和修改内容来更新网站。 由于这是一个开箱即用的站点范围更改,开发人员决定从头开始,重写项目,并借此机会解决当前 CSS 代码库存在但无法通过代码重构解决的核心问题,更新 CSS 技术堆栈,使用最新的工具和功能,建立新的内部规则和样式的最佳实践等。

让我们总结一下每种方法的优缺点。

重构改写
优点
  • 增量和灵活的过程
  • 使用单个代码库
  • 团队没有被重构任务锁定
  • 更容易说服利益相关者和项目负责人进行重构
  • 能解决核心问题; 过时的技术堆栈、命名约定、架构决策、内部规则等。
  • 独立于当前代码库(现有功能和弱点......)
  • 代码库可扩展性和可维护性的长期计划
缺点
  • 取决于当前的代码库和核心架构
  • 无法解决核心问题
  • 架构决策、现有的内部规则和最佳实践、广泛的问题等。
  • 执行起来可能很复杂,具体取决于项目设置和代码库运行状况
  • 昂贵且耗时
  • 需要在发布前全面实施
  • 在开发新代码库的同时维护当前代码库
  • 更难说服利益相关者和项目负责人进行完全重写

何时重构 CSS?

重构是一种推荐的方法,用于在保持当前外观(设计)的同时逐步改进 CSS 代码库。 当没有任何更高优先级的任务时,团队成员可以致力于解决这些代码库问题。 在大多数情况下,通过逐步改进当前的代码库用户体验不会直接受到影响,但是,更清洁和更可维护的代码库将导致更容易的功能实现和更少的意外错误和副作用。

项目利益相关者可能会同意将有限的时间和资源投入到重构中,但他们会期望这些任务能够快速完成,并期望团队能够完成主要任务。

当近期没有计划进行大范围的设计或内容更改时,应定期进行 CSS 重构。 团队应该在当前 CSS 代码库中主动寻找前面提到的弱点,并在没有更高优先级的任务可用时努力解决它们。

首席前端开发人员或对 CSS 最有经验的开发人员应该提出问题并创建重构任务,以在代码库中强制执行 CSS 代码质量标准。

何时重写 CSS?

当 CSS 代码库存在无法通过重构解决的核心问题或重构是更昂贵的选择时,应该重写完整的 CSS 代码库。 从个人经验来说,当我开始为从另一家公司搬来的客户工作时,遇到前面提到的 CSS 问题,很明显重构会很困难,我会首先建议完全重写,看看有什么客户认为。 在大多数情况下,这些客户对代码库的状态不满意,并乐于继续重写。

完全重写 CSS 的另一个原因是当网站计划进行重大更改时——重新命名、重新设计或任何其他影响网站大部分内容的重大更改。 可以安全地假设项目利益相关者意识到这是一项重大投资,并且需要一些时间才能完成重写。

审计 CSS 代码库运行状况

当开发团队同意需要重构 CSS 代码以简化功能开发工作流程或消除意外的 CSS 副作用和错误时,团队需要将此建议提交给项目利益相关者或项目经理。

提供一些硬数据以及对代码库和一般代码审查的主观想法是一个好主意。 这也将为团队提供一个可衡量的目标,他们在进行重构时可以了解这些目标——目标文件大小、选择器特异性、CSS 代码复杂性、媒体查询数量……

在进行 CSS 审核或准备 CSS 重构时,我依靠许多有用的工具中的几个来获得有关 CSS 代码库的一般概述和有用的统计信息。

我个人的首选工具是 CSS Stats,这是一个免费工具,它提供了对 CSS 代码库质量的有用概述,并提供了许多有用的指标,可以帮助开发人员发现一些难以发现的问题。

随机网站的 CSS Stats 报告的一部分,显示总 CSS 文件大小、规则数量、选择器、声明、属性等(大预览)
一个随机网站的 CSS Stats 报告的一部分,该网站的 CSS 代码库很差,具有高特异性选择器,这使得代码库难以维护。 his 是另一个用于跟踪和用于重构目标的有用指标。 (大预览)

早在 2016 年,trivago 就对其 CSS 代码库进行了大规模重构,并使用 CSS Stats 中的指标设定了一些具体的、可衡量的目标,例如降低特异性和减少颜色变化的数量。 在短短三周内,他们设法改善了 CSS 代码库的整体健康状况、减小了 CSS 文件大小、提高了移动设备的渲染性能等。

“像 CSS Stats 这样的工具可以轻松帮助您找出代码库中的一致性问题。 指出当每个人对灰色调的外观有不同的看法时会发生什么,你最终会得到 50 种灰色阴影。 此外,Specificity Graph 可以很好地整体指示 CSS 基础的健康状况。”

至于 CLI 工具,Wallace 是一个方便的工具,它提供了一些基本但有用的 CSS 统计信息和概述,可用于识别与文件大小、规则和选择器数量、选择器类型和复杂性等相关的问题。

我的个人网站的华莱士 CLI 报告示例(大预览)

Wallace 还在 Project Wallace 网站上提供了一个免费的分析工具,它在后端使用了一个看似更高级的 Wallace 版本,以提供一些有用的数据可视化和一些在 Wallace CLI 中不可用的指标。

随机网站的 Project Wallace 分析器工具示例的一部分。 注意从这几个统计数据中可以得出多少结论——太多的规则和选择器、太大的文件大小、太多重复的颜色和字体声明,等等。(大预览)

Project Wallace 还为CSS 代码库分析提供了完整的付费解决方案。 它具有更多有用的功能和指标,可以帮助开发人员捕捉一些难以发现的问题,并在每次提交的基础上跟踪 CSS 统计数据的变化。 尽管付费计划包含更多功能,但免费计划和基本的 CSS 分析器工具足以审核 CSS 代码库质量并获得总体概览以制定重构计划。

编写高质量的 CSS

我们已经看到 CSS 代码库的简单性和灵活性如何导致代码质量、性能和视觉错误方面的许多问题。 没有灵丹妙药的自动工具可以确保我们以最好的方式编写 CSS 并避免所有可能的架构陷阱。

确保我们编写高质量 CSS 代码的最佳工具是纪律、对细节的关注以及通用的 CSS 知识和技能。 开发人员需要不断地了解大局,并了解他们的 CSS 在大局中扮演的角色。

例如,通过过度指定选择器,单个开发人员可能会严重限制可用性,导致其他开发人员必须复制代码才能将其用于具有不同标记的其他类似组件。 当开发人员缺乏理解并且没有利用 CSS 背后的底层机制(级联、继承、浏览器性能和选择器特异性)时,通常会出现这些问题。 这些早期决定可能会在未来产生重大影响,因此 CSS 代码库的健康和可维护性取决于开发人员的知识、技能和对 CSS 基础知识的理解。

自动化工具不了解大局或选择器的使用方式,因此除了强制执行一些基本的、可预测的和严格的规则外,它们无法做出这些关键的架构决策。

从个人经验来看,我发现以下内容帮助我显着改善了我使用 CSS 的方式:

  • 学习架构模式。
    CSS 指南为基于通用编程模式和架构原则编写高质量 CSS 提供了丰富的知识库和最佳实践。
  • 练习和改进。
    从事个人项目或应对来自前端导师的挑战,以提高您的技能。 从简单的项目(单个组件或部分)开始,专注于编写最好的 CSS,尝试各种方法,应用各种架构模式,逐步改进代码,并学习如何高效地编写高质量的 CSS。
  • 从错误中学习。
    相信我,当你刚开始的时候,你会写一些质量很差的 CSS。 你需要尝试几次才能把它弄好。 花点时间想想哪里出了问题,分析弱点,想想你可以做些什么不同的事情以及如何做,并尽量避免将来犯同样的错误。

在团队甚至整个公司内建立规则和内部 CSS 标准也很重要。 明确定义的公司范围的标准、代码风格和原则可以产生许多好处,例如:

  • 统一且一致的代码风格和质量
  • 更容易理解,强大的代码库
  • 简化项目入职
  • 任何团队成员都可以进行标准化的代码审查,而不仅仅是首席前端开发人员或更有经验的开发人员

Kirby Yardley 致力于重构圣丹斯学院的设计系统和 CSS,并指出了建立内部规则和最佳实践的重要性。

“如果没有适当的规则和策略,CSS 是一种容易被滥用的语言。 开发人员通常会编写特定于一个组件的样式,而不会批判性地考虑如何在其他元素中重用该代码(……)在对我们想要如何构建 CSS 进行大量研究和考虑之后,我们决定使用一种称为 ITCSS 的方法。 “

回到前面 trivago 团队的示例,建立内部规则和指南被证明是他们重构过程的重要一步。

“我们引入了一个模式库,开始在我们的工作流程中使用原子设计,创建了新的编码指南,并采用了 BEM 和 ITCSS 等几种方法,以支持我们大规模维护和开发我们的 CSS/UI。”

并非所有规则和标准都需要手动检查和执行。 像 Stylelint 这样的 CSS linting 工具提供了一些有用的规则,可以帮助您检查错误并执行内部标准和常见的 CSS 最佳实践,例如不允许空的 CSS 代码块和注释、不允许重复的选择器、限制单位、设置选择器的最大特异性和嵌套深度、建立选择器名称模式等

结论

在决定提出细粒度的代码库重构或完整的 CSS 重写之前,我们需要了解当前代码库的问题,以便我们可以在未来避免这些问题,并为流程提供可衡量的数据。 CSS 代码库可能包含许多复杂的高特异性选择器,这些选择器在添加新功能时会导致意外的副作用和错误,可能代码库受到大量重复代码块的影响,这些代码块可以移动到单独的实用程序类中,或者可能是混合各种媒体查询正在引起一些意想不到的冲突。

CSS Stats 和 Wallace 等有用的工具可以提供 CSS 代码库的一般高级概述,并详细了解代码库的状态和健康状况。 这些工具还提供可测量的统计数据,可用于设定重构过程的目标并跟踪重构进度。

在确定重构目标和范围后,重要的是为 CSS 代码库设置内部准则和最佳实践——命名约定、架构原则、文件和文件夹结构等。这确保了代码的一致性,在项目中建立了可以记录的核心基础并可用于入职培训和 CSS 代码审查。 使用 Stylelint 之类的 linting 工具可以帮助强制执行一些常见的 CSS 最佳实践,以部分自动化代码审查过程。

在这个由三部分组成的系列的下一篇文章中,我们将深入探讨一种防弹的 CSS 重构策略,它确保当前代码库和重构代码库之间的无缝转换。

部分:CSS 重构

  • 第 1 部分: CSS 重构:简介
  • 第 2 部分:CSS 策略、回归测试和维护
  • 第 3 部分:优化大小和性能
  • 订阅我们的电子邮件通讯,不要错过下一个。

参考

  • “使用 ITCSS 管理 CSS 项目”,Harry Roberts
  • “Trivago 的大规模 CSS 重构”,Christoph Reinartz
  • “Sundance.org 设计系统和 CSS 重构”,Kirby Yardley
  • “从语义 CSS 到 Tailwind:重构 Netlify UI 代码库”,Charlie Gerard 和 Leslie Cohn-Wein
  • “CSS 审计工具”,Iris Lješnjanin