赢得自定义新的遗物弹球机!只需将数据书呆子提交以注册Futureestack。 现在注册

我们如何解决CSS版本冲突在这里的新遗迹

读了8分钟

在新的遗物中,用户界面基础架构团队为其其余部分提供组件。这些组件作为单个运输NPM.包,提供JavaScript和语法令人敬畏的样式表(Sass.)新的遗物团队可以通过他们的package.json文件引用。

由于我们的产品是由多个碎亚博最新版直播片构建的,我们可能偶尔会使用不同的内部NPM包构建的单个页面,这些包可能取决于新遗物UI的不同版本。然后,最新的包含版本的样式将覆盖页面中任何其他版本的样式。

由于NPM等工具的可用性,javascript中可能出现的冲突通常很容易解决;但CSS(层叠式床单)具有单一的全局上下文,缺乏上下文化的能力。我们必须为使用这些组件的New Relic团队想出解决这个问题的方法。

对于CSS版本传感器问题没有完美的解决方案 - 基本上,CSS中的双层碰撞 - 以及行业方法的不同之处来自一个全局CSS,这是防止双层夹杂物到涉及在JavaScript中写入所有CSS的方法的方法。每种方法都有福利和缺点,但我们希望分享我们如何解决问题的希望,希望我们的解决方案能够告知您自己努力处理CSS冲突。亚博直播平台

我们的解决方案有三个关键要求:

  1. Standard-following:CSS在公司范围内的公认标准是使用SASS,所以我们的版本控制解决方案也应该遵循它。此外,我们希望利用CSS/SASS的健壮工具。
  2. 可扩展性和override-ability:尽管我们的UI组件包的目标是标准化所有产品的行为和外观,但是转换必须是小块的。亚博最新版直播因此,如果组件不符合团队的需求,团队可能需要覆盖单个样式的能力。
  3. 生产代码中的零开销:我们希望最大限度地减少对运行时的影响,因此涉及为每个节点调用几个JavaScript函数的解决方亚博直播平台案没有取悦我们。

解决方案开发

考虑到这些要求,我们迭代不同的解决方案。亚博直播平台让我们走过一些代码样本来说明我们的方法。

这就是我们的CSS的样子:

.nr-table {overflow-y:滚动;& - 黑暗{背景:#333;}&-Cell {显示:Flex;身高:2EM;} //更多规则......}

第一个解决方案包含额外的类中的SASS包装所有根类。然后,每个组件的根元素将包括这些类。对于上面的示例,它将如下所示:

.v5-0-1 {//注意,应用于根元素的规则是//在不同的选择器(“&。#{$ root}”中包装)。&.nr-table {overflow-y:滚动;& - 黑暗{背景:#333;应用于子元素的规则是保留的。.nr-table {&-cell {display:flex;身高:2EM;}}}

这将输出选择器:

.v5-0-1.nr-table {...} .v5-0-1.nr-table  -  dark {...} .v5-0-1 .nr-table-cell {...}

使用这些选择器,您可以与根元素的主类一起使用(示例中的NR-Table) - Version Class(v5-0-1):

  <! - 内容...  - >  

我们计划在所有组件中通过辅助程序和JavaScript在SAS中添加根类,并通过所有组件中的公共基类。这将暗示最小的代码更改。但是,我们很快就发现了这种方法问题。

我们的许多组件都可以接受其他子组件,例如作为儿童的链接或按钮。在我们使用的示例中,可以将链路插入一个表格单元格中。但这会产生表版本和链接版本之间发生碰撞的可能性:

   <跨度类=”NR-Link-Content“>花式外部页面   

在上面的HTML中,NR-Link-Content与版本4.3.1如所预期的匹配,也与表版本有5.0.1(即,选择器.v5-0-1)。这种碰撞破坏了我们想要实现的版本沙箱,从而使解决方案无法使用。

修复CSS双层COllision.

要解决此问题,我们决定使用版本前缀每个类。这种方法不会影响选择器的特殊性。但是,将版本添加到每个类的过程变得过于复杂,无法手动完成,因此我们决定自动化它。

首先,我们选择了一个唯一的前缀。所有课程都已从NR-开始,但我们认为这太过泛,所以我们改变了它。在我们的案例中,我们选择了NR-CSS-。然后,我们浏览了所有UI基础架构CodeBase,以确保此组合未在其他任何地方使用。最后,我们明确表示NR-CSS-隐式意味着一个类:所有类必须以NR-CSS开头,只有在谈论CSS类时,您只能使用NR-CSS。

Next, we developed two Webpack loaders that do AST (Abstract Syntax Tree) traversing (using Gonzales-Pe for SASS, and Babylon + Recast for JavaScript) to find all Literals and TemplateLiterals containing nr-css and modify them by prepending the version (e.g., nr-css-link-content becomes v4-3-1-nr-css-link-selector). Webpack loaders are transformations applied on a resource file of your app. They are functions (running in Node.js) that take the source of a resource file as the parameter and return the new source.

虽然它看起来很复杂,但两个装载机每个都有小于60行,并在大约一天写。

微调覆盖

如上所述,有时临时覆盖是必要的,同时采用旧UIS上的组件,因为看起来不兼容。

因此,我们的最终解决方案略微修改了版本的预先添加到每个类。我们提取版本号,反转它们,将它们转换为两位字母代码(仅使用字母的基数26中的数字)。例如,版本2.9.114被转换为EKAJAC(AC为2,AJ为9和EK为114)。

这允许对覆盖进行微调选择。理论上,库的用户不应该覆盖样式。然而,采用过程不是瞬时的,可能会出现一些不一致,因此我们提供了在该过程中引入一些有意的摩擦的同时推翻的可能性。版本“哈希”在如何定义覆盖时扮演一个重要的角色:

让我们想象我们希望在NR-CSS-Table-Cell中覆盖某些内容。它是2.9.114版的完整CSS选择器是Ekajac-NR-CSS-Cell。根据您从中选择多少(通过CSS属性选择器),您可以决定版本覆盖:

EKAJAC-NR-CSS-Cell-Cell示例

UI Infrastructure团队还提供SASS帮助程序,可以将所需的覆盖组合到组合的属性选择器中。例如,为了覆盖版本2.9中的所有补丁(即,〜2.9),消费者将写入:

@include nr-css-override("table-cell", 2,9){背景:红色;}

然后将其编译为CSS:

[class * =“ajac-nr-css-table-cell”],[class $ =“ajac-nr-css-table-cell”] {背景:红色;}

我们解决CSS版本的问题

我们决定使用对当前码比的影响最小的解决方案,以及对性能的可忽略的影响。在最终方法中,零附加的JavaScript在每个渲染上都执行。

我们还提供了一种微粒的覆盖自定义规则,以便在采用库的同时缓解转换。这也让我们决定将来禁用这些规则,立即使所有UI一致。再次,我们希望这展望我们的解决方案可以帮助解决您可能面临的任何CSS版本问题。

前新型遗物领先软件工程师米格尔吉梅内斯丰德丽为这篇文章做出了贡献。