CSS 工程化概述
CSS 的问题
类名冲突的问题
当你写一个 CSS 类的时候,你是写全局的类呢,还是写多个层级选择后的类呢?
你会发现,怎么都不好:
- 过深的层级不利于编写、阅读、压缩、复用。
- 过浅的层级容易导致类名冲突。
一旦样式多起来,这个问题就会变得越发严重,其实归根结底,就是类名冲突不好解决的问题。
重复样式
这种问题就更普遍了,一些重复的样式值总是不断的出现在 CSS 代码中,维护起来极其困难。
比如,一个网站的颜色一般就那么几种:
- primary
- info
- warn
- error
- success
如果有更多的颜色,都是从这些色调中自然变化得来,可以想象,这些颜色会到处充斥到诸如背景、文字、边框中,一旦要做颜色调整,是一个非常大的工程。
CSS 文件细分问题
在大型项目中,CSS 也需要更细的拆分,这样有利于 CSS 代码的维护。
比如,有一个做轮播图的模块,它不仅需要依赖 JS 功能,还需要依赖 CSS 样式,既然依赖的 JS 功能仅关心轮播图,那 CSS 样式也应该仅关心轮播图,由此类推,不同的功能依赖不同的 CSS 样式、公共样式可以单独抽离,这样就形成了不同于过去的 CSS 文件结构:文件更多、拆分的更细。
而同时,在真实的运行环境下,我们却希望文件越少越好,这种情况和 JS 遇到的情况是一致的。
因此,对于 CSS,也需要工程化管理。
从另一个角度来说,CSS 的工程化会遇到更多的挑战,因为 CSS 不像 JS,它的语法本身经过这么多年并没有发生多少的变化(CSS3 也仅仅是多了一些属性而已),对于 CSS 语法本身的改变也是一个工程化的课题。
如何解决
这么多年来,官方一直没有提出方案来解决上述问题。
一些第三方机构针对不同的问题,提出了自己的解决方案。
解决类名冲突
一些第三方机构提出了一些方案来解决该问题,常见的解决方案如下:
命名约定
即提供一种命名的标准,来解决冲突,常见的标准有:
- BEM
- OOCSS
- AMCSS
- SMACSS
- 其他
CSS in JS
这种方案非常大胆,它觉得,CSS 语言本身几乎无可救药了,干脆直接用 JS 对象来表示样式,然后把样式直接应用到元素的 style 中。
这样一来,CSS 变成了一个一个的对象,就可以完全利用到 JS 语言的优势,你可以:
- 通过一个函数返回一个样式对象
- 把公共的样式提取到公共模块中返回
- 应用 JS 的各种特性操作对象,比如:混合、提取、拆分
- 更多的花样
这种方案在手机端的React Native中大行其道
CSS module
非常有趣和好用的 CSS 模块化方案,编写简单,绝对不重名。
解决重复样式的问题
CSS in JS
这种方案虽然可以利用 JS 语言解决重复样式值的问题,但由于太过激进,很多习惯写 CSS 的开发者编写起来并不是很适应。
预编译器
有些第三方搞出一套 CSS 语言的进化版来解决这个问题,它支持变量、函数等高级语法,然后经过编译器将其编译成为正常的 CSS。
这种方案特别像构建工具,不过它仅针对 CSS。
常见的预编译器支持的语言有:
- less
- sass
解决 CSS 文件细分问题
这一部分,就要依靠构建工具,例如 webpack 来解决了。
利用一些 loader 或 plugin 来打包、合并、压缩 CSS 文件。