zhangxinxu / gulp-qcss

write css quickly as rocket!
24 stars 1 forks source link

虽然本项目名称中出现了gulp,但是,千万不要误导。实际上,gulp只是偏角一隅,本项目不仅支持gulp使用,还支持纯node.js使用,还支持web版使用等。

QCSS - CSS快速书写和新式CSS压缩小工具

自己弄的一个Node.js小工具,本打算作为私藏水果刀平时随便用用,一番折腾和试用,发现原来是把斩仙刀,可以好好整整推一推。

关于QCSS

QCSS是Quick CSS的缩写,寓意是CSS书写快步如飞!

平常我们写CSS是这样:

.class-a {
  width: 300px;
  height: 150px;
  position: absolute;
  left: 100px;
  top: 100px;
}

如果QCSS书写,则是:

.class-a {
  w300; h150; abs; l100; t100;
}

少写了好多代码,感觉自己又年轻了许多。

下面视频为QCSS编译为CSS的录屏,实际上书写的时候是一次保存,全部编译,视频为了演示,每写一句编译了一次。

QCSS本质上也是个预编译工具,和Less,Stylus工具相比,更专注于CSS快速书写能力,嵌套,函数全部都不支持,但支持自定义变量。

更专注意味着更简单,更高效,同时在书写这一块更极致。

简单高效:基于映射规则的字符替换,无任何依赖,仅几K JS大小,移植到web上几乎无成本;
书写极致:可以自定义属性缩写,还可以自定义属性值缩写,甚至还可以自定义多个CSS声明片段缩写。仅需要分号分隔,px单位默认可缺省。

如何使用QCSS?

1. 纯node.js使用

项目根目录下的node-qcss.js中有两个变量,为pathSrcQcsspathDistQcss,分别对应QCSS文件目录和编译出来的CSS文件所在目录。

只要配置这两个路径为你所需要的路径。然后,直接下面这一句就可以使用了:

node node-qcss

直接node-qcss.js这个JS就可以了,可以在任意目录位置,运行后,自动QCSS编译并开启资源监控,非常轻便轻量。

默认node-qcss.js会在同目录下寻找qcss-web这个模块,如果没有,就会直接在线拉取最新的qcss-mapqcss-web这两个模块(只会执行一次)。

因此,实际开发只需要:

  1. node-qcss.js放在合适位置;
  2. 配置其中pathSrcQcsspathDistQcss的路径值;
  3. node node-qcss运行;

就完成啦,非常简单轻便!

2. gulp插件使用

gulp插件核心代码为根目录下的index.js

实际使用,步骤如下:

  1. 按照gulp-qcss插件:
    npm install gulp-qcss
  2. 注册任务:
    var gulp = require('gulp');
    var qcss = require('gulp-qcss');
    // gulp任务
    gulp.task('default', function () {
    gulp.src('src/test.qcss')
           .pipe(qcss())    // 或者.pipe(qcss('sass')) 如果有需要的话,默认是.css后缀
        .pipe(gulp.dest('dist/'));
    });

    然后就可以啦!具体可以参见/test/目录中的测试兼演示。

3. web中使用

主要是项目根目录下的qcss-web.js。默认为模块化加载:

module.exports = function (data) {

}

如果希望直连,可以改造下:

var qcss2css = function (data) {

}

其中data指QCSS字符内容,返回的是编译后的CSS字符内容。

如果直连,则依赖的qcss-map.js也要内联到qcss-web.js中。

4. postcss使用

本质上Qcss是个解析器,因此,无法作为postcss插件使用。使用示意:

let qcss = require('../qcss-web.js');
const postcss = require('postcss');
const fs = require('fs')

let parse = (css, opts = {}) => {
    return postcss.parse(qcss(css), opts);
}

fs.readFile(__dirname + '/src/test.qcss', 'utf-8', (err, css) => {
    postcss([{
        postcssPlugin: 'postcss-qcss'
    }]).process(css, {
        from: __dirname + '/src/test.qcss', 
        to: __dirname + '/dest/test.css',
        parser: parse
    })
    .then(result => {
        fs.writeFile(__dirname + '/dest/test.css', result.css, (err) => {
            if (!err) {
                console.log('dest/test.css编译成功');
            }
        })
    }).catch(error => {
        console.error(error)
    })
})

详见 ./test-postcss-qcss/run.js

可以执行下面的命令体验:

npm install

node test-postcss-qcss/run

QCSS实现的原理

本质上就是个正则替换。

我们对HTML字符进行转义的时候,会这么处理,一个映射对象,一个正则替换,如下:

var keyMap = {
  '<': '&lt;',
  '>': '&gt;',
  '&': '&amp;'
};
xxx.replace(/<|&|>/g, function(matchs) {
  return keyMap[matchs];
});

QCSS的实现也是如此:

keyMap = {
  dn: 'display: none',
  db: 'display: block',
  m: 'margin: ',
  ml: 'margin-left: ',
  …
};
css = qcss.replace(/* 替换细节 */);

QCSS的映射规则

· QCSS支持CSS属性缩写替换,例如:width -> w · QCSS支持CSS声明缩写替换,例如:display: none -> dn · QCSS支持多个CSS声明替换,例如:text-overflow: ellipsis; white-space: nowrap; overflow: hidden -> ell

不仅如此,QCSS还支持属性值关键字的映射,例如:color: currentColor -> c cc,前面的ccolor属性的缩写,后面的cccurrentColor关键字的缩写。

完整映射规则可参见:/qcss-map.js

内置的规则为自己多年缩写习惯,很多命名都是借鉴zxx.lib.css[https://github.com/zhangxinxu/zxx.lib.css] 由于不是粉色的(指人民币),不可能所有人都喜欢这样的命名规则,所以,建议可以根据自己的习惯和喜好进行修改,添加。

QCSS的其他功能

QCSS还支持自定义属性值变量,变量的声明是在注释中,变量名$开头,可以使用等号或冒号连接变量值,例如:

/*
$blue = #00a050;
$light = #eee;
$font: 'Microsoft yahei';
*/

会替换下面这个:

.class { bg light; ff font;}

为下面这样:

.class { 
    background: #eee;
    font-family: 'Microsoft yahei'
}

QCSS衍生出的超高压缩比CSS压缩工具css2qcss

根据实际测试,QCSS文件比CSS文件体积可以小30%~50%(试选择器复杂度),很多人会表示,反正最后上线的都是CSS文件,哪怕你QCSS文件小80%也没有意义啊,其实不然。

由于Service Worker的存在,我们可以把QCSS直接注册在浏览器中,于是我们可以直接请求.qcss文件,节省流量传输。

为此,我特意写了个创新的CSS压缩工具,css2qcss.js,可以把目前的标准的CSS文件全部压缩成QCSS这种缩写形式,配合Service Worker,就可以让网站在CSS资源这块的传输小30%~50%,注意,这是相比压缩的CSS文件的数据,如果是开发版的CSS,则压缩率甚至可以到60%,比JavaScript主流压缩工具还要厉害。

该压缩工具核心方法见:/css2qcss.js,依赖映射模块/qcss-map.js和CSS压缩模块/mini/cssmin.js

然后自己想要压缩文件的时候,读写文件即可,具体案例可参见:https://github.com/zhangxinxu/gulp-qcss/blob/master/mini/run.js

代码如下:

/**
 * 压缩测试的脚本
 */
const fs = require('fs');
const css2qcss = require('../css2qcss');

fs.readFile('./test/extra.css', 'utf8', (err, data) => {
    let length = data.length;
    //去除注释
    data = css2qcss(data);

    fs.writeFile('./test/extra.qcss', data, function () {
        console.log('extra.qcss压缩成功,尺寸减小了:' + 
          Math.round(10000 * (length - data.length) / length) / 100 + 
        '%');
    });
});