去年4月,Facebook透露了其重大新设计。一个雄心勃勃的项目,它重建了一个拥有大量用户的大型网站。因此,他们使用了React等多种创建和开源技术,GraphQL,Relay和一个叫stylex的新CSS-in-JS库。
这个新库位于Facebook内部,但他们已经分享了足够的信息,从而使开源实现style9成为可能。
为什么要使用另一个CIJ库?
CSS已经很多了-in-JS(CIJ)库,所以可能不明显为什么需要另一个。就像Christopher一样 根据Chedeau的说法,style9具有与其他CIJ解决方案相同的优势,包括范围选择器、无效代码消除、确定性分析和CSS和JavaScript之间共享值的能力。
但是,style9有几件事是独一无二的。
运行时间最少
虽然风格是由JavaScript定义的,但编译器会将其提取到传统的CSS文件中。这意味着最终JavaScript文件中没有提供样式。剩下的只有最终的类名,在最小化操作时会有条件地应用它们,就像你通常所做的那样。这样可以减少代码束,减少内存使用,加快渲染速度。
由于这些值是在编译过程中提取的,因此不能使用真正的动态值。幸运的是,这些都不是很常见,而且因为它们是唯一的,所以不需要内联定义。更常见的是有条件地应用样式,当然可以支持样式。多亏了babel,局部常量和数学表达式也是如此。.evaluate。
原子输出
由于style9的工作原理,每个属性声明都可以通过单个属性制作自己的类别。例如,如果我们opacity,: 在代码中的许多地方使用它,它将只存在于生成的CSS中一次。这样做的好处是,CSS文件随着唯一声明数量的增加而增加,而不是声明总数。CSS文件可能会因为大部分属性被多次使用而大大缩小。例如,Facebook的旧主页使用413 压缩CSSKB。所有重新设计的页面都使用74 KB 。同样,较小的文件大小可以带来更好的性能。
有些人可能会抱怨生成的类名不是语义的,它们是不透明的,忽略了级联。这是真的。我们将CSS视为编译目标。但有充分的理由。通过质疑之前假设的最佳实践,我们可以改善用户和开发人员的体验。
此外,style9还具有许多其他优秀的功能,包括使用typescript的输入样式、消除未使用的样式、使用Javascript变量的功能以及对媒体查询、伪选择器和关键帧的支持。
使用方法
首先,像往常一样安装它:
npm install style9
style9适用于Rollup,Webpack,Gatsby和Next.js插件,它们都是基于babel插件的。存储库提供了关于如何使用它们的说明。在这里,我们将使用webpack插件。
const Style9Plugin = require(style9/webpack'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); module.exports = { module: { rules: [ // This will transform the style9 calls { test: /\.(tsx|ts|js|mjs|jsx)$/, use: Style9Plugin.loader }, // This is part of the normal Webpack CSS extraction { test: /\.css$/i, use: [MiniCssExtractPlugin.loader, 'css-loader'] } ] }, plugins: [ // This will sort and remove duplicate declarations in the final CSS file new Style9Plugin(), // This is part of the normal Webpack CSS extraction new MiniCssExtractPlugin() ] };
定义样式
创作风格的语法与其他库非常相似。我们从调用style9开始.create样式对象开始:
import style9 from style9; const styles = style9.create({ button: { padding: 0, color: 'rebeccapurple' }, padding: { padding: 12 }, icon: { width: 24, height: 24 } });
因为所有的声明都会导致原子类,比如flex: 等等,速记均background: blue无效,因为它们设置了多个属性。可以扩展属性,如padding,margin,overflow等将自动转换为其普通写法变体。使用TypeScript时,使用不受支持的属性时会出现错误。
解析样式
为了生成一个类名,我们现在可以调用返回函数style9.create。它接受我们想要使用的样式键作为参数:
const className = styles('button');
该函数的工作模式是优先考虑右侧的样式,并与左侧的样式合并,如Object.assign。以下内容将导致元素填充为12px,并带有rebecapurple文本。
const className = styles('button', 'padding');
我们可以有条件地使用以下任何格式:
// logical AND styles('button', hasPadding && 'padding'); // ternary styles('button', isGreen ? 'green' : 'red'); // object of booleans styles({ button: true, green: isGreen, padding: hasPadding });
编译过程中将删除这些函数调用,并将其替换为直接字符串连接。上述代码的第一行将被“c1r9f2e5”取代 ‘ hasPadding ? ‘cu2kwdz ‘ : “”.没有留下任何操作。
组合样式
通过使用属性名称访问样式对象并将其传递给style9,我们可以扩展样式对象。
const styles = style9.create({ blue: { color: 'blue; } }); const otherStyles = style9.create({ red: { color: 'red; } }); // will be red const className = style9(styles.blue, otherStyles.red);
就像函数调用一样,右侧的样式优先。然而,在这种情况下,不能静态分析类名称。相反,将属性值替换为类,并在运行过程中连接。这些属性被添加到CSS文件中,就像以前一样。
总结
CSS-in-JS的好处很真实。也就是说,当我们在代码中嵌入样式时,我们必须付出一定的性能代价。在施工过程中提取值,我们可以兼得两全。我们可以从定位风格和标记以及使用现有JavaScript基础设施的能力中受益,并生成最佳风格表。
假如style9听起来很有趣,请查看回购协议并尝试一下。如果您有任何问题,请随时提出问题或联系。