1
CSScomb.js
вторая жизнь
Михаил Трошев, Яндекс
MoscowJS, 26 июня 2014
2
Статистика
Наша команда:
6 городов
30 разработчиков
~10 пул-реквестов в день
3
Статистика
Наш код:
> 1 Мб исходного CSS
> 40 000 строк
~140 Кб после минификации
4
Коллективная разработка
большой и старый проект
непрерывная интеграция
автобусное число
коллективное владение кодом
5
Коллективная разработка
код-ревью
код-стайл
договоренности
инструменты
6
Инструменты
JavaScript: JSHint, JSCS, JSLint, ESLint
CSS: ???
7
Инструменты
CSScomb:
+ сортировка
– ничего больше
– PHP
– RegExp
8
Инструменты
TODO: CSScomb.js
9
Слагаемые успеха
10
Ингридиенты
парсер — Gonzales
обвязка — JSCS
модули — TODO
тесты — TODO
11
Схема работы
12
Gonzales AST
color: rgb(255,0,0)	
	
"	
	
['declaration',	
['property',	
['ident', 'color']],	
['propertyDelim'],	
['value',	
['s', ' '],	
['function',	
['ident', 'rgb'],	
['functionBody',	
['number', '255'],	
['operator', ','],	
['number', '0'],	
['operator', ','],	
['number', '0']]]]]
13
Преобразование узлов
processTree: function(tree) {	
this._handlers.forEach(function(handler) {	
this.processNode(['tree', tree], 0, handler);	
}, this);	
return tree;	
},	
	
processNode: function(node, level, handler) {	
node.forEach(function(node) {	
var nodeType = node.shift();	
handler.process(nodeType, node, level);	
node.unshift(nodeType);	
this.processNode(node, level, handler);	
}, this);	
}
14
Обработчик
process: function(nodeType, node) {	
if (nodeType === 'string') {	
if (node[0][0] === '"' && this._value === 'single’)	
node[0] = node[0]	
.replace(/"/g, '"')	
.replace(/([^])'/g, '$1'')	
.replace(/^"|"$/g, ''');	
else if (node[0][0] === ''' && this._value === 'double’)	
node[0] = node[0]	
.replace(/'/g, ''')	
.replace(/([^])"/g, '$1"')	
.replace(/^'|'$/g, '"');	
}	
}
15
На сегодняшний день
— консольный и модульный режимы работы
— lint-режим
— поддержка LESS и SASS
— сортировка + 24 модуля
— автоматическая генерация конфига (!!!)
— плагин для grunt
— плагины для IDE
TODO:
— поддержка Stylus
16
На сегодняшний день
github.com/csscomb/csscomb.js
$ npm i csscomb
версия — 2.0.5
мейнтейнер — @tonyganch
17
Пример
.test{	
-webkit-transition: -webkit-transform .6s;	
transition: transform .6s;	
-webkit-transform: scale(.6,.6);	
transform: scale(.6, .6)}	
	
	
.test	
{	
-webkit-transition: -webkit-transform 0.6s;	
transition: transform 0.6s;	
-webkit-transform: scale(0.6, 0.6);	
transform: scale(0.6, 0.6);	
}
18
Пример
.select__separator{position:relative;z-index:3;float:left;width:
100%;margin-top:-1px;border-top:1px solid;font:0/0 a}	
	
	
.select__separator	
{	
font: 0/0 a;	
	
position: relative;	
z-index: 3;	
	
float: left;	
	
width: 100%;	
margin-top: -1px;	
	
border-top: 1px solid;	
}
19
Полезные ссылки
https://github.com/csscomb/csscomb.js
https://github.com/tonyganch/gonzales-pe
https://github.com/csslint/csslint
https://github.com/css/csso
https://github.com/goalsmashers/clean-css
https://github.com/jshint/jshint/
https://github.com/ikokostya/jshint-groups
https://github.com/mdevils/node-jscs
https://github.com/eslint/eslint
https://github.com/ariya/esprima
20
Спасибо за внимание!
21
Михаил Трошев
Руководитель службы поисковых интерфейсов
mishanga.pro
@ya_mishanga
Яндекс
22
Бонус-трек: оптимизация
170585 	search.sort.css	
165145 	search.css	
143685 	search.csso.css	
143685 	search.csso.sort.css	
142842 	search.clean.sort.css	
142744 	search.clean.css	
29315 	search.sort.css.gzip	
29117 	search.css.gzip	
27784 	search.csso.css.gzip	
27663 	search.clean.css.gzip	
27648 	search.sort.css.gz	
27619 	search.csso.sort.css.gzip	
27532 	search.clean.sort.css.gzip	
27495 	search.css.gz	
26357 	search.csso.css.gz	
26319 	search.clean.css.gz	
26208 	search.csso.sort.css.gz	
26099 	search.clean.sort.css.gz	
*.gz — zopfli --i15
*.gzip — gzip -7
*.sort.* — после запуска csscomb
*.csso.* — после csso
*.clean.* — после clean-css
Победитель:
clean-css + csscomb + zopfli

"CSScomb.js — вторая жизнь" — Михаил Трошев, Яндекс — доклад на MoscowJS 12