css-flat-loader
v0.2.1
Published
css flat loader module for webpack
Downloads
7
Readme
css-flat-loader
CSS Flat
CSS Flat(CSS 扁平化)是一种模块化解决方案,基于Post CSS生态开发。
主要解决问题:
- 达到模块化CSS的能力
- 解决由于业务的持续迭代,导致的CSS样式文件的线性增长问题(CSS Modules尤其明显)
CSS Flat 将CSS样式格式化为单条样式,开发时只需要按照正常文件书写:
.className {
display: block;
color: red;
margin: 0 auto;
}
.className:hover {
color: green;
magin-top: 10px;
}
Flat化之后:
.a-d-b {
display: block;
}
.a-c-1 {
color: red;
}
.a-m-2 {
margin: 0 auto;
}
.a-c_h-3:hover {
color: green;
}
.css-flat .a-mt_h-4:hover {
margin-top: 10px;
}
当你在js文件中 import CSS Flat文件时,会export一个对象,该对象包含Flat化之后 的信息(className: newClassNames):
import styles from "./style.css"; // { classNames: 'a-d-b a-c-1 a-m-2 a-c_h-3 a-mt_h-4 '}
// import { className } from "./style.css";
element.innerHTML = '<div class="' + styles.className + '">';
原则
- 仅处理单层类选择器
/* 不支持 */
.main.home-main {}
.main .title {}
.main span {}
#main {}
- 简写权重小于非简写权重
- 媒体查询权重大于普通样式,不同条件的媒体查询权重需自行配置
使用方法
npm install --save-dev css-flat-loader
目前依赖在CSS Modules的基础上来判断是否需要Flat话,后续会独立出来,详见demo
{
test: /\.less$/,
// loader: "style-loader!css-flat-loader!css-loader?modules!less-loader",
loader: ExtractTextPlugin.extract("css-flat-loader!css?modules&localIdentName=_[local]_!less")
},
stylelint设置
建议添加如下设置来对样式文件进行检测:
declaration-block-no-shorthand-property-overrides: true 查看
max-nesting-depth: [0, ignore: ["blockless-at-rules"]] 查看
selector-max-class: 1 查看
selector-max-id: 0 查看
API
// 配置文件css-flat.config.js
module.exports = {
plugins: [
require('precss')(),
require('autoprefixer')(),
]
}
注:对于px2rem, autoprefixer等推荐在css-flat.config.js的plugins中配置
flat后的样式公式如下:
.htmlClass*n .prefix-declProp(_(pseudo)(_atRule))-declValue {}
- htmlClass 根节点类名,用来增加权重,如margin-top的权重大于margin,n为'-'的个数
- 当atRule存在,但无伪类时,pseudo为空字符,但下划线(_)保留,避免冲突
- 当提供的map映射无相关属性时,脚本会自动从1自增分配,所以如需自定义提供map,不要提供数字,以免冲突
| 属性 | 类型 | 默认值 | 描述 |
| ---------- | --- | --- | --- |
|htmlClass
|{string}
|'css-flat'
|根节点类名,请自行在html标签上添加|
|prefix
|{string}
|'a'
|类名前缀|
|declPropMap
|{Object}
|见属性映射|属性映射|
|pseudoMap
|{Object}
|见伪类映射|伪类映射|
|atRules
|{Array}
|[]
|@规则的映射,如@media等,数组顺序代表权重|
|declValueMap
|{Object}
|见值映射|值映射|
|plugins
|{Array}
|[]
|插件|
|sourceMap
|{Bool}
|false
|sourceMap为true时,会保留css modules hash之后的类,但属性会改变成--sourceMap-xxx
, 间接达到sourceMap的功能|
更多
对于一些大型webview APP可按照规则容器内置通用common.css, 上线时做一次diff,仅需线上加载common.css不包含的CSS, 进一步降低样式文件,提升加载速度。
疑惑
css文件减少,那html或js文件增大了 答:没错,这是肯定的,不过不知你是否注意到,当你打开浏览器控制台查看元素,发现在元素上生效的样式并没有那么多条,更多的是层层覆盖。 针对该问题做了如下优化:
- 扁平化之前会使用cssnano进行合并
- 扁平化之后处理prefixer
- 规则尽可能简短
- 经过扁平化处理后注入到js中的也仅仅是一个对象,标签上也只是个对象值的引用
DOM节点的操作 答:经过处理后的类名是不具有可读性的,如果你使用的是react,那么也没必要操作dom,类名的可读性不再那么重要。如果你依然有操作dom的需求,你可以在模板中自行写类名。
sourceMap 答:这块的确不是特别好搞,目前的方案是开启sourceMap后,会保留css-modules hash后的类名,并将该类名下的样式自定义化使其不生效(如:--sourceMap-color: red),用于定位当前节点样式源文件的位置,基本可以满足需求。
简写和非简写的处理 答:优先使用cssnona进行合并,合并不了的遵循以下规则:非简写权重大于简写 如margin-top 会被处理成 .css-flat .xxx {margin-top: ...} border-top-left-radius 会被处理成 .css-flat.css-flat.css-falt .xxx {margin-top: ...} 所以你需要在html根节点上手动添加css-flat类名(可自定义) 对于媒体查询规则类似,只是权重可自定义,更加灵活
不支持嵌套,只支持类 答:对,该方案的核心思想就是扁平化处理css,对于嵌套我们不推荐,也不支持,如果你的项目已经组件化处理,单个组件的模板不会太大,也不应该太大,非嵌套的类方式不管从项目的后期可维护性上,还是浏览器的渲染上,都是利大于弊的。
样式合并 如style.button + style.disabled 答:推荐使用less如下方式:
.button{
}
.button-diabled{
.button()
}
因扁平化处理后的样式顺序改变不应该影响最终的渲染结果,所以单个html标签上的类名不应该出现相同属性的样式,直接使用style.button + style.disabled的方式是不安全的。 细心的朋友可能已经注意到我们的规则.prefix-declProp((pseudo)(atRule))-declValue {} 既有-又有 这两种分隔符,这里就是预留给处理相同属性的,你可以自己处理declProp((pseudo)(_atRule))相同的部分。
存在的问题
因开发中要支持样式文件的按需加载及热更新,无法过滤浏览器中已加载的样式,会很多重复的样式,在控制台中看着很不爽。上线时还需自行添加plugin处理重复样式。