CSS工程化方案

什么是css工程化,这个应该是目前前端的一个热点方向,如果在日趋复杂的项目更合理的维护和迭代,这个问题个人尤为重要,下面将展开目前我所认知的常规方案

PostCss

什么是postcss,有人说它是后处理器,个人觉得其实它跟前处理器(预处理器)背后所做的现在已经没差。官网的解释是:PostCSS 是一个允许使用 JS 插件转换样式的工具。 这些插件可以检查(lint)你的 CSS,支持 CSS Variables 和 Mixins, 编译尚未被浏览器广泛支持的先进的 CSS 语法,内联图片,以及其它很多优秀的功能
简单来说,postcss它只具备解析能力,至于转换能力就需要依赖插件(200+)

处理过程:

Css –> PostCss(模块化,加前缀,兼容性,css语法检查) –> Css

postcss-import

用于css文件的合并

  • 02-plugins-main.css
1
2
3
4
5
@import "./02-plugins-module.css";
.box{
box-shadow: 0 0 3px rgba(255,255,255, .3);
}
  • 02-plugins-module.css
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/* css-reset */
*{
padding:0;
margin:0;
}
body{
margin: 10px 20px 10px 20px;
font-size:14px;
}
body{
background-color:#ffffff;
}
1
2
3
4
5
6
const atImport = require('postcss-import')
module.exports = {
plugins: [
atImport
]
};

执行合并操作

1
./node_modules/.bin/postcss src/02-plugins-main.css -o build/02-plugins-main.css

autoprefixier

用于适配不同浏览器,自动加前缀

1
2
3
4
5
6
7
8
const autoprefixer = require('autoprefixer')
module.exports = {
plugins: [
autoprefixer({
browsers:['last 2 verisons'] //指定最近两个版本
})
]
};
  • 执行加前缀操作
1
./node_modules/.bin/postcss src/02-plugins-main.css -o build/02-plugins-main.css

cssnano

用于资源压缩

1
2
3
4
5
6
const cssnano = require('cssnano');
module.exports = {
plugins: [
cssnano
]
};
  • 执行代码压缩操作
1
./node_modules/.bin/postcss src/02-plugins-main.css -o build/02-plugins-main.css

cssnext

用于解析css新特性(已定稿,但浏览器未实现)

  • 03.cssnext.css
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
:root {
--mainColor: red;
--danger-theme: {
color: white;
background-color: red;
};
}
a {
color: var(--mainColor);
}
.danger {
@apply --danger-theme;
}
1
2
3
4
5
6
const cssnext = require('postcss-cssnext');
module.exports = {
plugins: [
cssnext,
]
};
  • 执行解析操作
1
./node_modules/.bin/postcss src/03.cssnext.css -o build/03.cssnext.css

结果:

1
2
3
4
5
6
7
8
a {
color: red;
}
.danger {
color: white;
background-color: red;
}

precss

它类似于sass,能够解析变量,条件if,循环,mixin,import,属性引用

  • 04-precss.css
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$blue: #056ef0;
$column: 200px;
.menu {
width: calc(4 * $column);
}
.menu_link {
background: $blue;
width: $column;
}
.notice--clear {
@if 3 < 5 {
background: green;
}
@else {
background: blue;
}
}
@for $i from 1 to 3 {
.b-$i { width: $(i)px; }
}
1
2
3
4
5
6
const precss = require('precss');
module.exports = {
plugins: [
precss
]
};

执行解析操作

1
./node_modules/.bin/postcss src/04.precss.css -o build/04.precss.css

结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.menu {
width: calc(4 * 200px);
}
.menu_link {
background: #056ef0;
width: 200px;
}
.notice--clear {
background: green
}
.b-1 { width: 1px; }
.b-2 { width: 2px; }
.b-3 { width: 3px; }

此外,PostCss它还可以跟其他构建工具集成使用,除了自己的PostCss-Cli,还可以跟Gulp,Webpack,Grunt,Rollup等等

gulp-postcss

  • 创建配置文件gulpfile.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const gulp = require('gulp');
const autoprefixer = require('autoprefixer');
const cssnano = require('cssnano');
const atImport = require('postcss-import');
gulp.task('postcss', function () {
var postcss = require('gulp-postcss');
return gulp.src('src/02-plugins-main.css')
.pipe(postcss([
atImport,
autoprefixer({
browsers:['last 2 versions']
}),
cssnano
]))
.pipe(gulp.dest('build/'));
});
  • 执行解析操作
1
gulp postcss

webpack

在webpack中,js是整个应用的核心入口,也就是说css最终会被转为js,并且插入到dom中去

  • 创建webpack.module.js,并暴露出去
1
2
3
4
5
module.exports = {
say: function(){
console.log('hello from module');
}
}
  • 创建webpack.main.js,引入webpack.module.js
1
2
3
var module = require('./webpack-module.js');
module.say();
  • 执行操作
1
./node_modules/.bin/webpack src/webpack.main.js build/webpack.main.js
  • 创建一个html文件,引入压缩后的js文件
1
2
...
<script src="build/webpack-main.js"></script>

直接require一个js文件没问题,如果我们在js直接require一个css文件的话,它是会报错,因为我们需要给它指定对应loader去处理css

1
2
3
4
5
6
7
8
9
10
11
module.exports = {
module: {
rules: [
{
test: /.\css$/,
use: ['style-loader','css-loader']
}
]
}
}

首先css-loader负责会把css文件转为js文件交给webpack处理,再style.loader把变成js的css文件注入到页面中

由于直接require一个css文件后,它的所以选择器的属性都暴露在全局中,会引起干扰,我们需要给他一个命名空间或者私有空间,让他们不会有冲突。

cssModule就是来处理这种问题,可以在css-loader中配置它

1
2
3
4
5
6
7
8
9
10
11
12
13
14
module.exports = {
module: {
rules: [{
test: /.\css$/,
use: ['style.loader', {
loader: 'css-loader',
options: {
modules: true
}
}]
}]
}
}

这个时候,css中的所有选择器名字都变了不能直接使用,但是require一个css文件, 使用cssModule用它会返回一个class列表, 通过style.[类名]去访问对应样式。

感谢您的阅读,本文由 lynhao 原创提供。如若转载,请注明出处:lynhao(http://www.lynhao.cn
Vue之Tab组件开发
Note For SVG