Черговий метод знизити обсяг SPA програми (webpack)

Так вже сталося, що останнім часом мені доводиться освоювати нові інструменти. Черговим таким інструментом став webpack.
Інструмент цікавий, але після переїзду з Google Closure * для мене стало загадкою, чому webpack не утискає імена класів, як це робить Google Closure Stylesheets.
За день, на коліні, мною був написаний plugin який цілком не погано реалізував цей функціонал.
Більш докладний опис нижче.

І так почнемо з ТЗ. Це робиться, по-перше, для себе, по-друге, для тих хто ще не зрозумів, що ту відбувається, але якимось чином потрапив на цю сторінку.
Особисто я люблю писати великі і красиві довгі імена класів, за яким відразу зрозуміло, що відбувається.
Наприклад:
.header {
position: fixed;
top: 0;
...
}
.header a {
display: block;
float: right;
...
}
.sidebar {
float:right;
max-width: 30%;
...
}
.sidebar a {
font-size: 16px;
....
}

Але можна ж скоротити header h, a sidebar s, таким чином заощадивши не мало байт не тільки в CSS, але і JS файли, т. к. швидше за все ваш JS буде містити селектори по іменах класів.
Однак, від такого скорочення буде страждати читаність коду, а як наслідок і швидкість розробки. З цього треба створити інструмент для проведення даної заміни автоматично.

Невелике пояснення як це працює в Closure

Google Closure складається з декількох інструментів, один з яких Google Closure Stylesheets, який є і препроцесором і постпроцессором для таблиць стилів.
Як препроцесор він аналогічний всім своїм побратимам, але більше всього він схожий на SCSS/SASS.
Як постпроцесор він парсити імена класів створюючи словник замін і замінює всі імена класів на їх короткі позначення.
На приклад, код вище стане:
.a {
position: fixed;
top: 0;
...
}
.a a {
display: block;
float: right;
...
}
.b {
float:right;
max-width: 30%;
...
}
.b a {
font-size: 16px;
....
}

А словник замін буде:
{
"header": "a",
"sidebar": "b"
}

Насправді функціоналу там набагато більше, але стаття не про те.
Є ще Closure Templates, непоганий шаблонизатор, в якому треба зазначити всі імена класів спеціальною директивою, що б потім застосувати словник замін до шаблонів.
Наприклад:
{namespace test}
 

 
/**
 
* Test template
 
*
 
*/
 
{template .test}
 
<div class="{css header}">Header<a href="#">Home</a><a href="#">About</a><header>
 
...
 
<div class="{css sidebar}">Sidebar<header>
 

Так само не треба забувати, що у нас є JS в якому теж треба «доопрацювати» імена всіх CSS класів:
var header = goog.dom.getElementByClass(goog.getCssName('header'));
var sidebar = goog.dom.getElementByClass(goog.getCssName('sidebar'));

І тільки коли ми виправимо всі вихідні коди і відправимо їх на компіляцію, разом зі словником замін, то все запрацює.
Головний недолік цього методу, що словник зібраний з CSS, тобто якщо у вас є клас який використовується тільки для вибірки DOM елемента з JS, то в словнику він може не потрапити (а може і потрапити, але зазначу, що дана стаття не огляд Closure Tools).

Повернемося до плагіну

Розкидати всюди функції, мені здалося не дуже зручно, по цьому я вирішив задавати імена класів по масці ___<%className%>__.
Таким чином стилі прийдуть до виду:
.___header__ {
position: fixed;
top: 0;
...
}
.___header__ a {
display: block;
float: right;
...
}
.___sidebar__ {
float:right;
max-width: 30%;
...
}
.___sidebar__ a {
font-size: 16px;
....
}

А робота з DOM в JS, на прикладі jQuery:
var header = $('.___header__');
var sidebar = $('.___sidebar__');

На прикладі React:
function Header(props) {
return (
<div className="___header__">
{props.children}
</div>
);
}

На прикладі Backbone:
module.exports = Backbone.View.extend({
tagName: 'div',
className: '___header__'
});

Обмовлюся відразу, що конструкції типу:
var genClassName = function(v) {
return '___' + v + '__';
}
module.exports = Backbone.View.extend({
tagName: 'div',
className: genClassName('header')
});

працювати не будуть.
Так само як і стилі:
[class*="bold"] {
font-weight:bolder;
}


Перші кроки

Встановивши пакет:
npm install --save cssrename-webpack-plugin

І трохи доопрацювавши webpack.config.js:
const CssRenameWebpackPlugin = require('cssrename-webpack-plugin');
...
module.exports = {
...
plugins: [
CssRenameWebpackPluginConfig,
...
]
};

У процесі складання з'явиться рядок:
«Profit: 355»
Яка буде повідомляти про те скільки байт було зекономлено.

Незручності та їх вирішення

Але якщо в тваринний різноманітному світі JS існує величезна кількість бібліотек, які одним парсером не покрити, то ось CSS в цьому питанні значно гуманніше, і розпарсити його (CSS) значно простіше.
У найпростішому вигляді це буде одне регулярний вираз. За цим чому б не додати подібний loader який позбавить нас від додавання нижніх підкреслень хоча б до CSS.
npm install --save cssrename-loader

Чергові мутації webpack.config.js:
module.exports = {
module: {
loaders: [
{
test: /\.css$/,
loader: "style-loader!css-loader!cssrename-loader"
}
]
}
};


Те що вийшло з тестовим проектом
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.