现代前端工程 CSS 方案调研
date
Apr 4, 2022
slug
css_solutions
status
Published
tags
web
type
Post
URL
summary
Author
随着这几年前端技术的快速发展,前端工程化里的 CSS 方案也在一直更新,本文简单总结分享一下目前比较常见的一些 CSS 方案。
首先可以大概分为四个大类:
- CSS 预处理器
- CSS Modules
- CSS-in-JS
- CSS 原子化
CSS 预处理器
CSS 预处理器是出现比较早的一种 CSS 方案,比较流行的预处理器方案有 Less、SASS、Stylus、PostCSS。
这几个方案各有优缺点,其中 Less 最简单,语法也比较简单,出现的也比较早可以搭配各种构建工具使用,缺点就是编程能力太弱,这部分 SASS 比较强大一点,但是SASS 一是语法太强大二是NPM安装比较麻烦,所以很多人也不是很喜欢用,觉得简单的Less 就足够用了。
Stylus 是一个富于表现力、动态的、健壮的 CSS 方案,因为写法和普通的CSS 方案差别比较大,所以这个受众也比较小。PostCSS 虽说也是预处理器,但是和其他三个有点不一样,它是一个使用JavaScript 工具和插件转换 CSS 代码的一个工具,它的强大之处在于可以结合很多插件来处理CSS,它可以达到预处理器的作用,但是它的功能不仅于此。
CSS Modules
JS在 ES6 之前诟病最多的就是缺少原生的模块功能,CSS 也是如此,没有模块功能导致写的一些CSS经常被全局污染需要写很多嵌套,为此社区出现了 CSS Modules这一技术方案,它就是为了给 CSS加了局部作用域和模块依赖功能。CSS Modules 是在编译的时候会给你的类生成一个全局唯一类名, 一出来就受到很大的关注,因为大家真的不喜欢给 CSS 类取名,有了它就不用担心会有 CSS 冲突了,也不需要写各种嵌套了。
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F2eaa50c0-c1a7-4cb7-a12f-f00b00b6fa40%2FUntitled.png?table=block&id=57dabf1e-1514-4cbe-b77f-c85ca621e7eb&cache=v2)
CSS-in-JS
随着React 的流行,在JS里面写CSS也开始变得慢慢流行起来,随着不断发展和迭代目前社区存在的几种CSS-in-JS 方案如下:
- styled-components
- emotion
- vanilla-extract
- stitches
- compiled
其中styled-components是最早流行的该方案,著名React 框架 Next.js 还内置了该CSS 方案,它把HTML原生标签封装到styled对象里面,把CSS 以字符串的形式传入,还支持传入props 动态生成CSS,最后会生成一个class。而且styled-components 因为出现的比较早,生态成熟,提供了各种编辑器插件提升开发体验。
但是因为所有带样式的基础HTML标签在styled-components以React组件存在,大量使用对性能带来一定影响。
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fbb231caf-e4ec-44c6-8127-47c4db63850b%2FUntitled.png?table=block&id=89647222-018e-4d5a-af3e-9b49d5253515&cache=v2)
emotion 是一个高性能、灵活的CSS-in-JS库。介绍两种使用方式,一种是和框架无关,一种是在React 里使用。在React中使用第一行注释是说明让babel用 jsx 函数对jsx文件进行处理,而不是 React.createElement。最后都会生成一个 class。
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fcb7a3ba8-13c4-4874-9d08-c0e2f09972a8%2FUntitled.png?table=block&id=12c17334-e0fc-42af-a71e-6b4bc9ea0d52&cache=v2)
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F34f11623-6a30-43e4-9d35-ca3a6bae59e6%2FUntitled.png?table=block&id=887b7947-6d84-43c5-a359-a4344a2a9d57&cache=v2)
emotion 支持 Object Styles 和 String Styles 两种写法。
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fb8396e96-3359-4db9-a56c-848351693f8b%2FUntitled.png?table=block&id=eb8b1f75-522e-429a-80c7-a1f893c770fc&cache=v2)
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F002e7ca7-45e2-4a65-a8a2-c29c4748843e%2FUntitled.png?table=block&id=1f1d75f4-a93c-4845-bfe8-7e114fba048a&cache=v2)
emotion 通过 @emotion/styled 还支持styled-components的语法,而且比styled-components有更小的文件和更快的渲染速度。它还支持SourceMap,调试也更方便。
vaillan-extract 是一个 Zero-runtime Stylesheets-in-TypeScript的 CSS 框架,将样式写入TypeScript(或JavaScript)中,使用局部作用域的类名称和CSS变量,然后在构建时生成静态 CSS 文件。
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fa0efc5e2-8172-4571-beb6-a85629bd575d%2FUntitled.png?table=block&id=141bee44-91d2-4497-a523-3b711d3ceffb&cache=v2)
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fa7229da1-f78b-4514-8e98-b74fcbd5ef90%2FUntitled.png?table=block&id=b579f08b-8d65-4e9d-bfa7-274d6de58b20&cache=v2)
它的实现和前端框架无关,可以搭配不同的构建工具使用,支持局部作用域的类名和 css 变量,zero-runtime 保证了在构建时生成了所有的样式,性能方面比styled-components这些方案要好。
stitches 是一个接近零运行时,支持SSR的轻量高性能的 CSS-in-JS解决方案。官方提供和框架无关的使用方式以及React的使用方式。
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fc8da398a-b118-4bb0-9ea2-e019bc36815f%2FUntitled.png?table=block&id=40f7bc16-5b67-4481-840d-cf9d890f3365&cache=v2)
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F1fa8f334-8177-4705-9015-cb0dfabd3eb9%2FUntitled.png?table=block&id=fd795ddf-8c9f-4183-8d40-efc742222997&cache=v2)
stitches 性能好,但是没有那么夸张,仅比emotion打包出来的体积小一点点,搭配TS开发体验很好,但是不支持字符串形式的 CSS 声明。
compiled 一个熟悉且高性能的适用于React的css-in-js库,TS支持很好,开发体验不错,提供多种使用方式。缺点就是比较新,社区生态啥的比较差,不建议直接上生产使用。
如图:提供 styled,CSS Prop,ClassNames 三种写法。
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F56e01ef5-ff05-4c61-8bfd-151ec189250d%2FUntitled.png?table=block&id=43ff1ede-e3ca-4f4c-8f4b-18f21573c7da&cache=v2)
综合来说 css-in-js 里面比较突出的方案还是 emotion。
原子化CSS
原子化css其实不是一个新鲜的方案,记得早期没有前端构建工具的时候就有人讨论过这种写法,但是在当时大家并不认同这种写法,但是最近随着TailwindCSS在国外的流行,大家又开始关注了,TailwindCSS能流行起来一是它确实做的比较强大和完善,二来也是现在的构建工具比较强大,支持很多自定义功能。
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F08fb9a69-a48f-4d48-aa92-610edd7ca643%2FUntitled.png?table=block&id=2ece863f-b2ca-4ba7-8095-523c1a7316fd&cache=v2)
Tailwind CSS 是一个功能类优先的 CSS 框架,它集成了诸如 flex, pt-4, text-center 和 rotate-90 这样的的类,它们能直接在脚本标记语言中组合起来,构建出任何设计。
不过虽然 Tailwind CSS 比较流行了,但是它的争议还是很多,和很早之前质疑这些原子化CSS的说法都差不多,比如说类名太多,难以维护扩展等。国内的相关争议可以在知乎上看看大家的讨论 https://www.zhihu.com/question/337939566
Windi CSS 是下一代工具优先的 CSS 框架。可以把 Windi CSS 看作是按需供应的 Tailwind 替代方案,它为你提供了更快的加载体验,完美兼容 Tailwind v2.0,并且拥有很多额外的酷炫功能。可以认为是开发体验更好的 Tailwind。
UnoCSS 是另外一个比较新的即时原子化CSS引擎,它的一个优点就是可以完全自定义规则,如果能接受原子化CSS的但是不想被tailwind css预先设计的样式约束 可以尝试一下。
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F3709bb9c-6ad7-41f0-b385-52c7f7b7117f%2FUntitled.png?table=block&id=f494c006-c054-4381-905e-2c96db3fd241&cache=v2)
总结
最后再总结一下我个人会在什么场景使用什么方案:
大型项目,多人协作的项目:CSS Modules 是个不错的方案,不用担心 CSS 冲突。
个人开发维护的小项目:Tailwind/Windi CSS 是不错的方案,可以使用 Less 做备选。
组件库:可以考虑使用 emotion 这些 css-in-js 方案,一个组件在一个文件里就能写完,不需要创建那么多的css 文件。