当前位置: 首页 > 科技观察

CSSinJS菜鸟:Vanilla-Extract分析

时间:2023-03-13 22:34:31 科技观察

转载请联系Tecvan公众号。前言2021年,vanilla-extract作为一匹黑马,高居css-in-js满意度榜首(虽然使用率只有1%)。它声称是一个类型安全且高度兼容的TS场景库。国内相关讨论还很少。稍微看一下,还是挺有用的。官网文档介绍:https://vanilla-extract.style/documentation/打开vanilla-extract官网文档,上面列出了它的优点。作为一个在使用css-in-js时更喜欢styled-components的人,主要关注点是:所有样式都是在构建时生成的通过CSSType类型安全的样式。说白了,这两点就是零运行时和支持typescript。零运行时:vanilla-extract在编译时会编译cssmodules值和css内容,不会给生产环境带来任何运行时内容,相对来说运行速度更高,产品体积更小;typescript:支持typescripttypeCheck,CSSsecurity;目前业界的相关竞品如styled-components大多是runtime解决方案,基于标签模板编写,主要基于stylisparser解析,如果频繁更新props也会造成大量的style标签被插入头部。Webpack环境下,需要同时安装@vanilla-extract/css和@vanilla-extract/webpack-plugin插件:yarnadd@vanilla-extract/css@vanilla-extract/webpack-plugin安装完成后,修改Webpack配置:const{VanillaExtractPlugin}=require('@vanilla-extract/webpack-plugin')module.exports={entry:'./src/index.js',//....plugins:[newVanillaExtractPlugin()]};这里可以看到,我们在使用vanilla-extract时,需要安装两个库:@vanilla-extract/css:开发核心库,基于该库进行项目业务风格开发;@vanilla-extract/webpack-plugin:webpack插件。前面也提到了vanilla-extract是一个零运行的库,主要是通过这个插件来处理的。通过添加webpack配置项,使用自定义的@vanilla-extract/webpack-plugi/loader处理相关后缀文件。内部使用eval库在编译时执行className结果,避免运行时的执行过程;然后去掉@vanilla-extract/css库,这样就不会影响生产环境下js包的大小;构建样式API这里只提到vanilla-extract核心构建样式相关的几个API,其他API可以直接到官网查看。styleimport{style}from'@vanilla-extract/css';exportconstparentClass=style({background:'red',':hover':{background:'blue',},});exportconstchildClass=style({选择器:{'&:nth-child(2n)':{background:'#fafafa',},[`${parentClass}&`]:{color:'pink',},},});import{childClass,parentClass}from'./index.styles.css';constDemo=()=>(DEMO1

DEMO2
DEMO3
);exportdefaultDemo;相信这是一个简单的demo,看几眼就明白如何使用了。但需要明白的是,为了提高可维护性,“每个样式块只能针对某个元素(或使用该样式块的元素)”。那么,对于上面代码中的选择器,“它的目标必须是”**&**(即它自己的元素),而不是其他元素。例如:`${parentClass}&`可以,但不允许使用`&div`。我觉得这种设计更多的是职责分离。每个样式块都针对某个元素,这样对于项目来说,样式的可维护性大大提高。与js中的其他css(styled-components)相比,不容易出现样式冗余的问题。对于一些特殊情况,比如:在编写styled-components时,我们会用它来包裹arco组件(或其他组件),然后对其内部元素覆盖或添加新的样式。constStyledSelect=styled(Select)`div{color:red;}`那么就不能直接在vanilla-extract样式块中完成,因为每个样式块都是针对某个元素的,不能直接通过样式块.直接调整其兄弟元素和子元素的样式。但是,对于这种情况,可以使用另一个APIglobalStyle进行开发。globalStyle,顾名思义,就是全局样式API。但是因为vanilla-extract本身使用了css模块,每个className都是唯一的,所以通过globalStyle调整其子元素的样式是完全可行的。import{style,globalStyle}from'@vanilla-extract/css';exportconstparentClass=style({});globalStyle(`${parentClass}>div`,{color:'red'});constDemo=()=>(