好用的CSS模块化打包工具CSS-COMBO_weixin_33755847的博客-程序员宅基地

技术标签: ViewUI  开发工具  前端  php  

上半年在团队做自动化之类的工作,也学习了NodeJS,确实,NodeJS很适合做一些小工具神马的,今天我给大家介绍的就是我自己基于NodeJS写的CSS模块化打包工具:CSS Combo,项目地址:https://github.com/daxingplay/css-combo

说起模块化,前端一般谈JS模块化的居多,毕竟JS是编程语言,比如业内的seajs、KISSY loader等,都有很成熟的模块化规则和方案了,前端工程师可以采用模块化的方法去编写页面,打包,上线,但是CSS界却没有。

后来,CSS界出现了SASS、LESS之类的语言,这些语言的出现可以说是非常应景的,有一点很重要,拿LESS举例,less支持了模块化,你可以@import ‘xxx.less’的形式导入其他less文件(模块),方便模块化。我也正是从这点得到了灵感,想出了如何去做css模块化。

CSS模块化

其实,CSS规范里面就已经提到相关内容了,就是@import语法。这个语法是被当前主流浏览器(当然包括ie6)原生支持的。具体怎么用我想我不用在这里浪费大量篇幅给大家介绍语法,大家可以看下mozilla里面对@import语法的解释(链接),为啥大家很少用呢,大概很大一部分原因是因为steve的这篇博文。确实,如果在生产环境单独去用@import,会有较为严重的性能,而且不同的浏览器以及不同的用法下也有不同的表现,比较让人郁闷。但是,这并不妨碍@import成为CSS模块化的利器。

想必@import诞生就是为了解决css模块化的问题吧。我们先来举一个例子看看CSS模块化的优势:

传统的开发

假如你要开发某大型网站首页,那html的head里面应该是这样引用样式的:

<link href="/path/to/style.css" rel="stylesheet" type="text/css">

为了页面上比较好的性能,减少创建http请求的消耗,我们一般会选择尽量减少link的css文件数量,假如本例中,页面上所有的样式都写在了style.css里面。可想而知对于一个大型网站来讲,这个文件会有多长多长多长长长长。。。。如果出现bug或者想改个东西,肯定找半天;而且现在界内对于CSS开发并没有很成熟的最佳实践或者约定可循,很多时候,前端为了加快进度,可能会把某一个功能的代码放在css不同的地方,如果想下线某个功能,肯定不敢乱删。

这时候,CSS模块化的优势就体现出来了!

模块化开发

页面不改,我们还是只引用那一个样式,style.css,但是文件内容改成下面的:

/**
 * xxx页面入口样式文件style.css
 */

@import './utils/base.css';

/*页面基础框架(骨架)*/
@import './mods/layout.css';

@import './mods/header.css';
@import './mods/nav.css';

/*首页焦点图*/
@import './mods/flash-pic.css';

………这里省略诸多模块………

@import './mods/footer.css';

这里,我们把style.css中混乱的样式划分成了一个一个的子文件,作为模块。可以看到,作为示例,我把页面的一些reset样式以及一些站点公用样式放在了util目录下的base.css中,把页头拆分成header.css,把首页焦点图的样式单独拆分成falsh-pic.css,把页面的基础布局都放在了layout.css这个文件中。然后相应的代码就在对应的模块中写,是不是看起来简洁、好维护很多?

不光是简洁,使用@import形式的模块化还有下列好处:

  1. 浏览器原生支持。这点是这个工具或者这种模块化形式的亮点。对于less,想要在开发环境下方便地修改,还需要额外引入一个js文件,或者采取less实时编译之类的方法。对于实时编译,像我这种用idea编辑器自动保存的人很蛋疼,每次自动保存的时候less编译报错。。。而采用这种@import xxx.css文件的方法,我们可以很方便地在开发阶段,直接调试。不需要引入额外的js文件去解析style.css文件。页面中直接引入style.css文件,通过http瀑布图可以看到,base.css、layout.css等被一个一个加载进来了。
  2. 方便下线某个功能。这个是所有语言模块化的优势,比如哪天PD说,首页焦点图那个地方我想换个样式,以往,我们很多都是直接在html里面改掉原来的class,然后在style.css里面直接加上新的样式,老的也不敢删,怕删错了,即使删了也可能会漏,因为不停的bugfix可能会导致代码乱写。而采用模块化的方案,我直接把@import ‘./mods/flash-pic.css’这一行注释掉,然后再@import新的样式,这样,即使上线了,PD说效果不好,想换回原来的,只要改一下注释,重新打包,岂不是很方便?
  3. 便于管理各种日常需求。好,页面做好了,上线了,PD今天脑袋抽风,说我要加一个功能,首页右侧加一个建议反馈入口,以往,我们要打开style.css,想想在哪儿加好,或者直接加在最后,也不管最后的地方是放什么的。采用模块化之后,我们在style.css的最后再@import ‘./mods/feedback.css’即可,然后加上注释:/* 2012-12-06 PD要求加上建议反馈 */,这样以后其他修改者也能快速知道你这个模块是干神马的。
  4. 方便合作开发。这也是所有语言模块化的优势。对于一个大型项目,往往共同开发一个文件,冲突的可能性非常大,很多情况下,我改了一个小地方,提交上去就冲突了,然后再花费比bugfix多10倍的时间去解决冲突,然后还不知道会不会产生另外10个新bug,而模块化,每个人负责哪些模块,职责非常明确,不容易出现问题。
  5. 依赖写在入口文件,而不是打包脚本的配置文件。这样开发和打包分离,新加、减少模块不需要去修改打包配置,方便多人协作
  6. 方便调试,这是非常重要的特点,我会在后面详细阐述。

好,说完CSS模块化,以及如何利用@import形式来组织自己的模块,大家是不是感觉这种形式让你眼前一亮呢?慢着,steve大牛不是说这种@import方式有性能问题么?

是的,如果这样开发完直接上线的话,页面会有一些问题,我就不拿steve的博文再说一遍了,感兴趣的同学可以自己去看看大牛的文章。我就挑一些比较明显的问题说一下:

  1. 因为@import的文件是额外请求的,所以页面加载的时候会有一小会儿的裸体(样式没加载进来),要等这些模块一个一个加载
  2. 请求数太多,页面性能不佳,对服务器压力也会相对大一些。
  3. steve大牛提到的不同的浏览器以及不同的书写形式可能会有不同的加载顺序。

所以,最好的办法就是把模块打包!这和js模块化一样的,模块化开发,然后上线之前打包,线上完美使用。

CSS Combo:CSS模块打包利器

像js打包,一般都会有配备的打包工具。比如seajs有他的spm,kissy有我写的module-compiler(NodeJS版本)等等,对于css,很多人是用ant的concat或者grunt的concat,这样做的不利的一面就是要把css模块依赖写在打包脚本的配置文件中,很不利于维护。很多时候,你新增了模块,忘记了修改打包脚本的配置,然后发上去发现我的脚本怎么没生效?查了半天才发现是没打包进去。

如果你利用我上面介绍的@import形式来组织你的css,那么你就可以用我写的配套打包工具CSS Combo了:

首先安装css combo:

npm install -g css-combo

然后进入你所在的入口文件(本例为style.css)目录,输入:

csscombo style.css style.combo.css

这样就会把style.css文件打包成style.combo.css文件。很简单吧。当然还有其他参数,请见github文档

好吧,你不喜欢用命令,或者你想整合该工具到你自己的一整套打包工具中,可以到github上看相关的api文档:https://github.com/daxingplay/css-combo

如何利用CSS模块化方便调试

模块化,非常重要的一个特点就是要方便调试。否则我把压缩之后的打包文件发上去了,发现线上出bug了怎么办?这里,你只需要选择一个代理工具将style-min.css(或者style.combo.css)文件代理成你的源码文件style.css,然后刷新一下,看看是不是都模块加载了?

或者,我也推荐你用这种方案,和开发配合起来,比如后台是php,我可以在引用style-min.css的时候这么写:

if(!empty($_GET['css-debug'])){
    echo '    <link href="http://xxx/style.css">';
}else{
    echo '    <link href="http://xxx/style-min.css">';
}

这样,在线上,你可以在url后面加上css-debug参数,那么页面就引用了style.css脚本,样式文件全部模块化载入,方便你调试,能够快速定位到出错的模块;而普通访客进来,没有加这个参数,全部是引用的style-min.css这个压缩之后的脚本。

当然,你也可以任意发挥,比如在淘宝内部,我们可以结合ucool方便切换源码和非源码,或者使用现成的代理工具,比如windows下的fiddler等,当然你可以在js脚本里面,把源码的link标记删除掉,在动态插入源码的link等等。

总之,利用模块化,可以很方便调试,定位出问题的代码在哪个文件。

一些最佳实践

首先,我务必要提醒大家,@import语法一定要仔细看。
基本上,以下几种用法:

@import "./mod/mod1.css";
@import "f:/website/htdocs/xxx/assets/css/mod/mod2.css";
@import url("http://assets.taobaocdn.com/tbsp/tbsp.source.css");

这里,我们不推荐使用本地绝对路径的引用方式,因为不利于团队协作,相对目录绝对够用了,当然css-combo是支持解析本地绝对路径的。

至于直接@import线上的路径,css-combo工具也是支持的,会帮你下载下来~

另外,一定要注意,CSS规范中,@import必须放在其他样式之前,比如:

@import "./mod/mod1.css";
@import "./mod/mod2.css";

body {
     margin:0; }

而下面这种写法:

@import "./mod/mod1.css";

body {
     margin:0; }

@import "./mod/mod2.css";

mod2.css是无法被浏览器@import进来的。所以我们推荐的最佳实践就是把所有的模块import都放在入口文件的最开始,方便管理。

其他

为啥不直接用less

团队里面不是每人都会less,不是每个人都喜欢less。而且less不支持gbk编码,还有上面提到的,调试需要引入一段js,很多情况下,开发套页面的时候都保留了。。。其实,最根本的原因就是less和css combo解决的不是一类问题,less更多的是把css编程化,css combo只专注css模块打包:)

好,先写到这儿吧,思路比较乱,大家有问题欢迎提出,对于css combo工具有任何需求和bug,欢迎到github上提issue。 (5603)

 

转自:http://www.techcheng.com/study/css/introduce-css-combo.html

转载于:https://www.cnblogs.com/mrxia/p/4206697.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_33755847/article/details/94133954

智能推荐

google protobuf安装与使用_羽生少年的博客-程序员宅基地_google protobuf

  google protobuf是一个灵活的、高效的用于序列化数据的协议。相比较XML和JSON格式,protobuf更小、更快、更便捷。google protobuf是跨语言的,并且自带了一个编译器(protoc),只需要用它进行编译,可以编译成Java、python、C++、C#、Go等代码,然后就可以直接使用,不需要再写其他代码,自带有解析的代码。更详细的介绍见:Protocol Buffersprotobuf安装1、下载protobuf代码google/protobuf2、安装pr..

运动模糊&运动拖影&果冻效应分析_free-xx的博客-程序员宅基地_运动模糊效应

1. 前言拍摄运动物体会出现运动模糊、运动拖影、果冻效应等问题;如何确定是哪种问题以及对应策略2. 运动模糊现象:原因: 曝光时间过长导致解决办法: 降低曝光时间可以解决此问题2. 运动拖影现象:原因: 开启WDR或HDR模式导致的,即多帧合一模式【一般是长中短帧曝光合成】; 一般是多帧合一的图像算法没做好导致,优化比较好的话是不会出现的解决办法: 优化多帧合一的图像算法,一般这都是第三方做好提供的,...

jQuery与其它库冲突的解决方法_helmsgao的博客-程序员宅基地

大家都知道jQuery它最强大的地方面在于其选择器功能 ,所以在开发应用软件,能让软件用户体验方面有意想不到的特效,在jQuery库中,几乎所有的插件都被限制在它的命名空间里。全局的对象都很好地存储在jQuery命名空间里,因此当把jQuery和其它javascript类库一起使用时,不会引起冲突. (提示一下:默认情况下,jQuery用$作为自身的缩写而以)如果jQuery类库和别的类库

kali中的webshell生成工具weevely_Vhagar的博客-程序员宅基地

用法usage: weevely [-h] {terminal,session,generate} ...参数:{terminal,session,generate}terminal Run terminal or command on the target #在目标上运行终端或命令session Recover an existing s...

OpenLayers3(三)混合地图切换_天空影的博客-程序员宅基地_openlayer百度混合地图

因为OpenLayers中没有提供混合地图这个api,然后项目要求需要和百度地图一样有混合地图这个功能,然后通过new ol.layer.Tile这个api找到了一些思路。附:OpenLayers初始地图思路1、需要两个完整的切片图层来达到可以混合地图切换功能 2、初始化地图博客中就有new ol.layer.Tile并且是通过这个来引入街道图切片 3、new ol.layer.T...

terminal终端命令_jupiter_888的博客-程序员宅基地

一、查询8082的端口netstat -ano|findstr 8082

随便推点

《RabbitMQ实战指南》---- RabbitMQ进阶(一)_jushisi的博客-程序员宅基地

1、备份交换器2、过期时间(TTL)3、死信队列(DLX)4、延迟队列5、优先级队列

win10 64系统如何换成win7 32系统?_薄荷味的猫丷的博客-程序员宅基地

win10 64系统能换成win7 32系统?当然可以,不少小伙伴跟快启动小编反映装了win10之后系统变得卡顿不堪,无奈之下只好换装win7 32系统。今天快启动小编带大家了解win10 64系统如何换成win7 32系统操作,希望大家能走出迷途。  一、注意事项:  1、预装的win10 64改win7 32需要改硬盘分区表,大家需要备份好硬盘所有资料,如果你原来电脑是xp

windows内核开发学习笔记三十九:内核概念之中断和异常_jyl_sh的博客-程序员宅基地_什么 passive-level interrupts

中断(interrupt)是处理器与外部设备打交道的重要途经;而异常(exception)则是处理器的正常指令流在执行过程中产生一些特殊事件,需要紧急处理才能继续原来的指令流。它们都会打断一个正常的指令流,但区别在于,中断的发生与当前指令流并无实质的联系,而异常则是当前指令流执行的直接结果。而且,中断是异步的,而异常是同步的。 尽管中断和异常的触发来源和方式不相同,Intel x86处理器内部使用同一套陷阱机制来处理中断和异常,它利用IDT(Interrupt Descri...

(转载)ubuntu 18.04 安装pytorch_小亭亭�的博客-程序员宅基地

第一步:安装pip3sudo apt-get install python3-pip顺便安装numpypip3 install numpy然后会提示你更新pip的版本,于是我就选择更新了pip3 install --upgrade pip第二步:配置pip使用的镜像源附:国内镜像源列表豆瓣(douban) http://pypi.douban.com/simple/清华大学 ...

多传感器同步_free-xx的博客-程序员宅基地_硬同步和软同步的区别

1. 硬件同步、硬同步:使用同一种硬件同时发布触发采集命令,实现各传感器采集、测量的时间同步。做到同一时刻采集相同的信息。 例: 可使用同一个脉冲触发板,不过需要多传感器硬件上支持2.软件同步:时间同步、空间同步。(1)时间同步、时间戳同步、软同步: 通过统一的主机给各个传感器提供基准时间,各传感器根据已经校准后的各自时间为各自独立采集的数据加上时间戳信息,可以 做到所有传感器时间戳同步,但由于各个传感器各自采集周期相互独立,无法保证同...

ArcEngine 9.3 学习笔记(五):地图和地图布局(PageLayout对象,Page对象,SnapGrid对象,SnapGuides对象,Element 对象,MapGrid 对象..._Fredok_915的博客-程序员宅基地

&amp;#13; 3.2 地图布局&amp;#13;3.2.1 PageLayout对象&amp;#13;  PageLayout用于显示地图数据,并通过对地图数据进行整饰以便对地图打印输出满足不同行业对GIS出图功能的需求。  PageLayout和Map这两个对象看起来非常相似,他们都是视图对象,可以显示地图;也都是图形元素的容器,可以容纳图形元素(Graphics Element)  区...

推荐文章

热门文章

相关标签