Angular 提供的 CSS 作用域机制很棒,但无疑会增加不少代码体积,特别是有使用 SSR(Server-Side Render) 的情况,因此,本文介绍尝试改用 CSS Module 来重新组织样式的方法。
技术点
1. BEM
BEM 是一套约束 CSS 书写的规范,该规范将类选择器划分成了 Block(B)、Element(E)、Modifier(M)。
- Block 用于描述可重用的标签快。
- Element 用于描述 Block 下的无法重用的标签块。
- Modifier 用于修饰 Block 或 Element 的状态。
2. CSS Module
使用 BEM 规范的类名通常比较长,为了进一步缩小打包代码后的体积,使用 CSS Module 工具将类名 hash:base64 处理。
约定
BEM 书写
Block 与 Element 使用 __
链接,Element 与 Modifier 使用 --
链接。
借助 webpack,同时为了避免书写上的麻烦,组建样式中除了组建根元素(:host
),其他类名不需要加 Block。例如:
1 | // app/app.component.scss |
最终生成的 CSS 代码将类似:
1 | .app { |
对于非组建样式(如全局样式),将统一自动拼接 common
作为 Block 名。例如:
1 | // style/post.scss |
最终生成的 CSS 代码将类似:
1 | .common__post-table { |
因此这类样式有冲突的风险。
组建与通用样式之间仅以目录结构作为区分。组建位于 src/app/components
下,通用样式位于 src/app/styles
下。
占位符
占位符用来替换模板及脚本文件中原先的类名。为便于实现,模板代码使用注释的副本。
- 模板:
<!--~ code ~-->
- 组建选择器:
%{tag}
- 组建样式类名:
.{class}
- 通用样式类名:
!.{class}
- 组建样式类名在脚本中的引用:
/*.*/
类名
BEM style class -> md5 -> base64:6
组建选择器
is-
[component name -> md5:6]
打包流程
- 使用 webpack 处理全部样式文件,生成 css 及 json 格式的类名 map 文件;
- 使用 css map 文件预处理组建模板及样式,输出到临时目录;
- 在
angular.json
中定义fileReplacements
(一次性定义),替换掉默认的组建模板及脚本文件; ng build
- 合并第 2 步生成的 css 文件到 dist。