前言
antd4以前的版本用less的变量来实现多套less模板,来渲染主题。局限性很大,所以antd5做了新的官方的css-in-js的主题实现,来控制更复杂的主题业务场景,接着我会展示源码细节并深入学习。
我的理解
按我的理解css-in-js就是将通过序列化css的属性名来实现css的模块化,所以你会看到webpack可以编译module.css的文件来隔离, 包括其他emotion、styled-components的cssinjs的方案的大放异彩,js控制样式自然灵活度极高,所以你几乎看不到css文件,但是同时你的项目内会有大量的js的编译代码,说白了打包出来的js文件会很大。antd5区别于其他方案,做了各种缓存
,以及更可控的组件级别的控制
,相比性能对于组件库的层面是要优于其他css-in-js的方案的
。
困境
css-in-js最大的问题在于你编写的css样式类名经过模块化后是不一致的,每次在react的重渲染下,大量的props带来额外性能开销也是很明显的。
Antd的css-in-js优缺点
Antd最大的特点是组件级别的缓存,那么hash最终的结果要受到组件名 + token + version 等,这么做很明显是为了props防止重渲染。对于我们的场景的业务场景你要考虑好组件名的唯一,也就是hash的唯一性,对于大型web应用管理hash也是一件头疼的事情。

源码
首先在任意一个antd5的component中你可以看到这段代码,useStyle返回的wrapSSR和hashId,hashId会被用于classNames的序列化样式属性中,那么重点是wrapSSR这个函数,函数传入了react的元素节点,大概率也能想到传入的节点要混入style对象。


//./style/index.tsx
export default genComponentStyleHook('Collapse', (token) => {const collapseToken = mergeToken<CollapseToken>(token, {collapseContentBg: token.colorBgContainer,collapseHeaderBg: token.colorFillAlter,collapseHeaderPadding: `${token.paddingSM}px ${token.padding}px`,collapsePanelBorderRadius: token.borderRadiusLG,collapseContentPaddingHorizontal: 16, // Fixed value});//返回的是一个通过js对象描述的一个样式表return [genBaseStyle(collapseToken),genBorderlessStyle(collapseToken),genGhostStyle(collapseToken),genArrowStyle(collapseToken),genCollapseMotion(collapseToken),];
});
你会看到