文章由ssh翻译/润色,原文地址首次发布公众号《前端从进阶到入院》,欢迎关注,加我好友一起讨论。随着Facebook和Twitter最近的产品部署,我认为一种新趋势正在慢慢发展:AtomicCSS-in-JS。在这篇文章中,我们将了解AtomicCSS是什么,以及它如何与TailwindCSS联系起来,TailwindCSS是一个实用程序优先的样式库,目前许多大公司在其React存储库中使用它。由于我不是这方面的专家,我不会深入探讨它的优缺点。我只是希望这可以帮助您了解它的含义。先说一个令人高兴的结论,新的编写和构建CSS的方式将Facebook主页上的CSS大小减少了80%。什么是原子CSS?您可能听说过各种CSS方法,例如BEM、OOCSS...Dangerbutton第一)概念。这与FunctionalCSS和Tachyon库的理念非常接近。Button由大量实用类Table组成的样式,所以我们可以在网页上展示我们的才华。原子CSS就像实用优先CSS的极端版本??:所有CSS类都有一个CSS规则。AtomicCSS最初由ThierryKoblentz(Yahoo!)在2013年挑战CSS最佳实践时使用。/*AtomicCSS*/.bw-2x{border-width:2px;}.bss{border-style:solid;}.sans{font-style:sans-serif;}.p-1x{padding:10px;}/*不是原子CSS,因为这个类包含两个规则*/.p-1x-sans{padding:10px;font-style:sans-serif;}使用utility/atomicCSS,我们可以将结构层和表现层分开结合:当我们需要改变按钮颜色时,我们直接修改HTML,而不是CSS!这种紧密耦合在现代CSS-in-JSReact代码库中也得到认可,但似乎CSS世界是第一个对传统的关注点分离提出异议的人。CSS权重也不是问题,因为我们使用的是最简单的类选择器。我们现在通过html标签添加样式,并发现了一些有趣的事情:随着我们添加新功能,样式表的增长速度变慢了。我们可以移动html标签并确保样式也能正常工作。我们可以删除新功能并确保同时删除样式。缺点肯定是html有点臃肿。对于服务器呈现的Web应用程序来说可能是一个缺点,但是类名中的高度冗余允许gzip压缩得很好。同时它很好地处理了之前重复的css规则。一旦您的实用程序/原子CSS准备就绪,它就不会改变或增长太多。它可以更有效地缓存(您可以将它附加到vendor.css并且它不会在重新部署时失效)。它还相当便携,可以用于任何其他应用程序。Utilities/AtomicCSS的局限性Utilities/AtomicCSS看起来很有趣,但它们也带来了一些挑战。人们通常手工编写实用程序/原子CSS,制定命名约定。但是很难保证这个约定易于使用、一致并且不会随着时间的推移变得臃肿。这个CSS可以协同一致地开发吗?受总线因素影响吗?总线因子是软件开发过程中软件项目成员之间信息和能力集中度的非共享度量,也被一些人称为“卡车因子”、“卡车因子”(lotteryfactor/truckfactor)。当一个项目或项目群失去至少部分关键成员的参与(“撞车”,指的是职业和生活方式的改变、结婚生子、意外伤亡等)导致项目变得混乱、瘫痪和无法进行时为了生存,这些成员的数量就是总线系数。在开始开发新功能之前,您还需要预先开发一个像样的实用程序/原子样式表。如果utility/atomCSS是由其他人制作的,那么您将必须首先学习类命名约定(即使您对CSS了如指掌)。这种约定是主观的,您很可能不喜欢它。有时,您需要一些utility/atomCSS不提供的额外CSS。没有商定的方式来提供这些一次性样式。Tailwind来支持Tailwind的方法很方便,解决了上面的一些问题。它通过Utility-First的理念解决了CSS的一些缺点,抽象出一组类名->原子函数,避免你为每个div写一个专有的类,然后在整个网站样式上重复很多次。传统卡片样式编写:Tailwind卡片样式编写:它并没有真正为所有站点提供一些独特的实用CSS,而是提供一些通用的命名约定。使用配置文件,您可以为您的网站生成一组自定义的实用CSS。ssh注:原作者这里没有深入介绍。为什么是一套命名规范而不是生成一些固定的CSS呢?举一些例子,Tailwind提供了一个强大的构建系统。例如它默认提供了一些响应式断点值://tailwind.config.jsmodule.exports={theme:{screens:{'sm':'640px',//=>@media(min-width:640px){...}'md':'768px',//=>@media(min-width:768px){...}'lg':'1024px',//=>@media(min-width:1024px){...}'xl':'1280px',//=>@media(min-width:1280px){...}}}}你可以随时更改配置文件中的这些断点,比如你需要的小屏sm可能指的是更小的320px,那么你想在小屏的时候使用flex布局,或者像往常一样写sm:flex,遵循相同的约定,但是这个sm已经被你修改为适合项目需求的值。比如Tailwind中的spacing就是负责表示margin、padding、width等各个属性所占空间的值。默认是使用rem单位。当你在配置中覆盖它时://tailwind.config.jsmodule.exports={theme:{spacing:{'1':'8px','2':'12px','3':'16px','4':'24px','5':'32px','6':'48px',}}}如果你写h-6(高度),m-2(边距),mb-4(边距-底部)),后面数字的含义由你自行更改。也许当你从桌面切换到移动项目时,6的含义就变成了6rem,但这一套约定却深深地烙印在你的脑海里,成为你知识的一部分。Tailwind的知识可以转移到其他应用程序,即使它们不使用完全相同的类名。这让我想起了React的“学习一次,随处编写”的理念。我看到一些用户反馈说Tailwind提供的类名可以满足他们90%-95%的需求。覆盖范围似乎足够广泛,以至于不经常编写一次性CSS。此时,您可能想知道为什么使用atomicCSS而不是TailwindCSS?一个规则,一个类名,强制执行原子CSS规则有什么好处?你最终会得到更大的html标签和更烦人的命名约定吗??Tailwind已经有足够的原子类。那么,我们是否应该放弃AtomicCSS的想法而只使用TailwindCSS?Tailwind是一个很好的解决方案,但仍有一些问题没有解决:需要学习一套主观命名约定CSS规则插入顺序仍然很重要未使用规则是否可以轻松删除?我们如何处理剩余的一次性样式?与Tailwind相比,手写原子CSS可能不是最方便的。比较CSS-in-JS和CSS-in-JS与utility/atomicCSS密切相关。这两种方法都提倡使用标签进行样式化。以某种方式尝试模拟内联样式,这为它们提供了许多相似的功能(例如在移动某些功能时更有信心)。ChristopherChedeau一直致力于在React生态系统中推广CSS-in-JS的理念。在许多演讲中,他解释了CSS的问题:全局命名空间依赖性死代码消除代码压缩共享常量非确定性解析隔离实用程序/原子CSS也解决了其中一些问题,但也确实无法解决所有问题(尤其是非确定性问题)样式解析)。如果它们有很多共同点,我们可以同时使用它们吗?探索AtomicCSS-in-JSAtomicCSS-in-JS可以被认为是“用于自动化的原子CSS”:您不再需要创建类名称约定通用样式和一次性样式以相同的方式处理能够提取页面需要的关键CSS并进行代码拆分有机会修复JS中CSS规则插入顺序的问题我想强调两个具体的解决方案,他们最近驱动了两个大规模部署atomicCSS-in-JS,来源于以下两个介绍。Twitter上的React-Native-Web(更多细节在NicolasGallagher的演讲中)。Facebook上的Stylex(更多细节在FrankYan的演讲中)。还可以看看这些库:StyletronFelaStyle-Sheetcxsotioncss-zeroui-boxstyle9stitchescatomReact-Native-WebReact-Native-Web是一个非常有趣的库,它允许浏览器也呈现React-Native原语。不过,我们在这里不是在谈论跨平台开发(更多细节在谈话中)。作为Web开发人员,您只需要了解React-Native-Web是一个常规的CSS-in-JS库,它带有一些原生的React组件。到处写View组件,都可以用div代替。React-Native-Web由NicolasGallagher编写,他曾在Twitter上为移动设备工作。他们正在逐步将其部署到移动设备上,不确定何时,可能在2017/2018年左右。从那时起,许多公司都在使用它(MLS、Flipkart、Uber、纽约时报……),但最重要的部署是由PaulArmstrong桌面应用程序领导的团队于2019年推出的新Twitter。StylexStylex是Facebook团队为2020年Facebook应用重构而开发的新CSS-in-JS库。它可能在未来开源,可能以另一个名称。值得一提的是,React-Native-Web的作者NicolasGallagher是被Facebook招进来的。因此,其中出现一些熟悉的概念也就不足为奇了。我所有的信息都来自演示文稿:),仍在等待更多细节。可扩展性不出所料,随着AtomicCSS的加入,Twitter和Facebook的CSS量都显着减少,并且其增长现在遵循对数曲线。但是,简单的应用程序的初始量会多一些。Facebook分享了具体数字:旧网站只用了413Kb的主页CSS,新网站整个网站只用了74Kb,包括暗模式源代码和输出。这两个库的API看起来很相似,但是很难分辨,因为我们对Stylex了解不多。值得强调的是,React-Native-Web会扩展CSS语法糖,比如margin:0,会在4个方向上作为margin原子规则输出。让我们以组件为例,看看旧的传统CSS和新的原子CSS输出之间的区别。.class1{background-color:mediumseagreen;游标:默认;margin-left:0px;}.class2{background-color:蓟;游标:默认;调整内容:flex-start;margin-left:0px;}可以看出这两种样式中的cursor和margin-left是完全一样的,只是在输出中会占用体积。让我们再看看原子CSS的输出:}classC{background-color:thistle;}classD{margin-left:0px;}classE{justify-content:flex-start;}可以看出,虽然标签上的类名比较多,但是输出CSS体积的增长会随着功能的增加而变慢,因为出现过一次的CSSRule不会再出现。产品验证让我们看看Twitter上的主题标签是什么样子的:现在,让我们看看新的Facebook:很多人可能会被吓到,但它效果很好并且仍然可以访问。在Chrome中检查样式可能有点困难,但在devtools中很清楚:CSS规则顺序不同于手写工具/原子CSS,而JS库使样式独立于CSS规则的插入顺序。在规则冲突的情况下,生效的不是标签上class属性中的最后一个类,而是样式表中最后插入的规则。以这张图为例,我们期望后面写的蓝色类会覆盖前面的类,但实际上CSS会根据样式表中的顺序来决定优先级,最后我们看到的是红色文字。在实际场景中,这些库避免在同一元素上编写具有冲突规则的多个类。他们会确保最后写在标签上的类名生效。其他被覆盖的类名被排除在外,甚至根本不会出现在DOM上。conststyles=pseudoLib.create({red:{color:"red"},blue:{color:"blue"},});//只会输出蓝色相关的CSSAlwaysblue!