TARS, зроби рівень frontend-рутини 0%

image

Frontend з кожним днем стає складніше. Завдання — об'ємніше, користувальницький інтерфейс — більш насиченим, HTML, CSS і Javascript — більший, а сон фронтендера — коротше і неспокійнішим. Необхідно грамотно структурувати код, виконувати безліч рутинних завдань (компіляція css і js-препроцесорів, збірка спрайтів, підготовка та оптимізація зображень, минификация файлів і ін). Якщо ви працюєте в команді — це автоматично збільшує складність розробки. Щоб вирішити ці проблеми, я створив TARS — складальник html-верстки, заснований на gulpjs.
<habracut/>
Ми в 2ГІС знаємо про frontend-рутині не з чуток. У компанії створюється багато веб-проектів різної складності: від порталів і онлайн-карти, до різних лэндингов і промо-сайтів. Ми втомилися від нудної копіпаста при роботі з html, підготовки графіки для дисплеїв з високою щільністю пікселів, минификации все, що тільки можна минифицировать і т. д. Здавалося, що всі ці речі машина може спокійно зробити за нас. Тому я вирішив розробити інструмент для автоматизації левової частки frontend-рутини.

Що хотілося отримати від цього інструменту:
  • автоматизувати все, що можна;
  • використовувати вже існуючі напрацювання, а значить використовувати знайомий нам мову програмування — JavaScript, знайому екосистему — Node.js і npm;
  • базовий набір функцій в одному інструменті;
  • зручне API;
  • кросплатформеність.
Перш ніж писати своє, спочатку ми колегами пошукали вже готові рішення. Знайшлося їх дуже багато. Ось витримка, як мені здається, найбільш цікавих проектів:
Кожен з цих інструментів хороший по-своєму: де-то є чудова документація, де-то добре реалізована система зберігання тасков. Але всі ці рішення або занадто складні для модифікування, або занадто прості, що простіше вже своє написати, ніж допрацьовувати існуюче. При цьому розширювати функціонал довелося б точно. Наприклад, жодне з рішень не надавало workflow підготовки графіки для екранів з високою щільністю пікселів.

Тоді народився TARS, який увібрав усе найкраще з вже готових проектів.

TARS — це набір gulp-тасков для автоматизації більшості завдань frontend'а + можливість легкого додавання нових, якщо буде чогось не вистачати. TARS можна назвати фреймворком для gulp. Підходить як окремим розробникам, так і великим командам. З TARS легко розробляти проекти будь-якої складності: від лендинга до величезного порталу. Вам навіть не потрібно знати, як працює gulp, так як все, що можна, було винесено в опції, весь код та варіанти використання задокументовані.

Ключові особливості у TARS.
  1. Jade або Handlebars як html-шаблонизатора або звичайний html (при виборі Handlebars).
  2. SCSS, Less, Stylus як css-препроцесора або ламповий CSS (підтримується синтаксис в рамках будь-якого з препроцесорів). Нещодавно з'явився проект fmp, в якому це теж доступна.
  3. Можливість відокремити дані від уявлення, передавши дані у вигляді js-об'єкта в шаблони. Так ми використовуємо один і той самий шаблон багато разів, але з різними даними, без копіпаста, бібліотек і фреймворків. Докладніше про це буде розказано нижче.
  4. Вотчер chokidar.
  5. По-справжньому розумна робота з зображеннями. Максимально спрощується розробка під екрани з високою щільністю пікселів. Про це буде розказано нижче.
  6. Легко розширювати своїми тасками. Модульна структура.
  7. Відмінна документація.
  8. Створення архіву готової збірки. Дрібниця, а приємно.
Ну і, звичайно ж, конкатенації, минификации і оптимізації всього, що тільки можна, кілька режимів збірки і т. д.

У TARS значний набір опцій, кожна з яких детально описана в документації.

Ми вже використовували TARS у розробці сайту про технології, продукти та дизайні
2ГІС, різних лендингов (Промо додатки 2ГИС для Windows Phone, франшиза 2ГИС для Казахстану, сайт внутрішньої конференції розробників 2ГІС), сайту 5pm та ін

Як все працює
Вам знадобляться:
  • Node.js (можливо, скоро і на IO.js працюємо над цим);
  • Gulp, встановлений глобально;
  • Архів TARS.
Після того, як ми завантажили архів, виконуємо команду gulp init. Вона підключить вибрані html-шаблонизатор і css-препроцесор (зазначаються в конфіги), створить базову файлову структуру. Все, можна ковбасити. TARS працює на всіх десктопних платформах.

У найближчому майбутньому зроблю yeoman-генератор.

Перш ніж розпочати роботу зі складальником, рекомендую ознайомитися з документацією.

Основні команди для складання
Всього є два основні команди:
  • gulp build (або просто gulp);
  • gulp dev.
Перша команда робить готову збірку проекту, а друга запускає TARS в режимі розробки. В dev-режимі проект збирається без минификаций і з запущеними вотчерами за файлами.

Команди розділені невеликою кількістю прапорів:
  • gulp build (або просто gulp) (--min, --release, --ie8);
  • gulp dev (--lr, --tunnel, --ie8).
З gulp build можна використовувати ключ --min, і тоді в html підключаться минифицированные js і css-файли. При використанні ключа --release в html підключаться всі ті ж минифицированные файли, у назві яких є рендомний hash.

З gulp dev використовуються ключі --lr для запуску livereload в браузері, який відкриється автоматично (браузер можна вибрати в конфіги). Ключ --tunnel расшарит верстку з вашого локального комп'ютера в зовнішній веб. Ви отримаєте посилання в консолі, по якій верстка буде доступна в інтернеті.

Також з будь-якою командою можна використовувати ключ --ie8, який запустить додаткові таски для складання з підтримкою браузера Internet Explorer 8. Браузер особливий, ось і workflow для нього особливий.

Всі інструкції з установки знаходяться в документації.

Структура проекту
У папці «tars» знаходяться всі файли складальника (вбудовані і призначені для користувача таски з вотчерами, різні хэлперы) і папка з исходниками проекту (markup). У корені лежить конфіг складальника, списки залежностей для проекту, конфіг для перевірки js code style і основний gulpfile.js.

├── gulpfile.js # gulpfile складальника
├── tars-config.js # Конфігураційний файл
├── package.json # Залежно TARS
├── user-package.json # Користувальницькі пакети
└── tars/ # Таски і хелпери для gulp
└── helpers/ # Хелпери
└── tasks/ # Основні таски
└── user-tasks/ # Користувальницькі таски
└── watchers/ # Основні вотчери
└── user-watchers/ # Користувальницькі вотчери
└── markup/ # Основна папка з проектом
└── modules/ # Модулі
└── pages/ # Шаблони сторінок
└── static/ # Різна статика (css, js і т. п.)
└── docs/ # Документація


Проект — це набір сторінок (папка pages), набір модулів (папка modules) і папка з різною статикою (static, за замовчуванням. Назву можна змінити в конфіги).

Сторінки — найбільш прості шаблони, які підключаються модулі. Найпростіший приклад модуля — menu або footer. Щоб стало зрозуміліше, в термінах БЕМ модуль — це блок. А якщо без БЕМ, то модуль — будь-яка самостійна сутність на сторінці.

exampleModule/ # Приклад модуля
└── assets/ # Різна статика для поточного модуля
└── ie/ # Стилі для ie8 і ie9 (ie9/ie8.scss|less|styl)
└── data/ # Папка для зберігання даних для модуля
├── data.js # Дані для модуля у вигляді js-об'єкта
├── exampleModule.html # Html|Jade-подання модуля 
├── exampleModule.scss|less|styl # Scss|Less|Stylus-подання модуля
├── exampleModule.js # Js-подання модуля


Кожен модуль має свою html, css і js-уявлення, папку для різних файлів для модуля (картинки, відео і т. д.), папку для стилів браузерів IE8 і IE9, папку з файлом даних для модулів. Всі перераховані файли і папки необов'язкові для модуля. Будь модуль може включати інші модулі.

Зовсім не обов'язково, що модуль — окрема сутність. Ви можете використовувати модулі так, як вам буде зручно.

Папка зі статикою може містити в собі підкаталоги для зберігання картинок, js-файли бібліотек і модулів, файли вибраного css-препроцесора + різні файли, які повинні в підсумку виявитися в корені проекту, наприклад, фавиконка або robots.txt

Обов'язково прочитайте, яким чином склеюються JavaScript і CSS, — від цього залежить те, як потрібно користуватися файлами збирача.

Файлова структура створюється автоматично під час ініціалізації проекту. Вона в цілому незмінна, але є ряд необов'язкових каталогів, плюс ряд опцій для зміни імені вже наявних папок збирача. Файлова структура детально описана в документації.

Для JavaScript створені окремі опції, в яких можна вказати, звідки ще потрібно брати js для склейки. Таким чином, не потрібно лізти в файли складальника, якщо ви хочете використовувати який-небудь фреймворк, в якому є така сутність, як модуль (або подання, або директива, або що там ще).

Робота з шаблонами
Припустимо, що у нас є сторінка, на якій є верхнє, бокове і нижнє меню. Приблизно така:



Меню дуже схожі один на одного, але мають різні посилання, невеликі відмінності в стилях. Далі будемо говорити в термінах БЕМ. Кожне меню — це блок. Набросаєм трохи html для реалізації меню, який у підсумку ми покладемо в папку modules (modules/menu/menu.html:

<nav class="menu">
<ul class="menu__list">
<li class="menu__listItem">
<a href="url" class="menu__listItemLink">title</a>
</li>
...
</ul>
</nav>


Я не буду наводити весь код, але очевидно, що онуча виходить цілком солідною. Тепер винесемо всі дані для цього меню (посилання і назви пунктів меню) в окремий файл (data/data.js у папці модуля):

menu: {
header: {
mod: 'header',
list: [
{
url: firstLinkUrl,
title: firstLinkTitle
}
...
]
},
side: {
mod: side,
list: [
{
url: firstLinkUrl,
title: firstLinkTitle
}
...
]
},
footer: {
mod: footer,
list: [
{
url: firstLinkUrl,
title: firstLinkTitle
}
...
]
}
}


Тепер трохи вдосконалимо наш шаблон для меню (використовуємо handlebars):

<nav class="menu {{#if mod}} _{{mod}} {{/if}}">
<ul class="menu__list">
{{#each list}}
<li class="menu__listItem">
<a href="{{r}}" class="menu__listItemLink">{{title}}</a>
</li>
{{/each}}
</ul>
</nav>


У цьому випадку додався якийсь mod, за допомогою якого ми зможемо кастомизировать CSS меню залежно від його стану.
Залишилося тільки підключити ці меню на сторінку:

<html>
<head></head>
<body>
<header>
{{> menu/menu menu.header}}
</header>
<aside>
{{> menu/menu menu.side}}
</aside>
<footer>
{{> menu/menu menu.footer}}
</footer>
</body>
</html>


З допомогою handlebars-хелперу «>» ми підключаємо модуль menu з поданням menu (кожен модуль може мати кілька подань) на сторінку і передаємо йому певні дані.

Разом ми маємо 1 шаблон + 1 файл з даними для меню, який використовується в двох різних місцях. Таким чином можна реалізувати модуль, який дуже зручно переиспользовать. Залишається тільки додати, що такий же функціонал реалізований і для jade.

Підготовка та зберігання графіки
Сьогодні існує багато екранів з високою щільністю пікселів. Розберемося, що це означає.

В якості прикладу розглянемо смартфони IPhone 3GS і IPhone 4. У 3GS роздільна здатність екрану 320x480, а у 4-ки — 640x920. Як ми бачимо, дозвіл збільшилася рівно в два рази при тій же діагоналі, а значить піксель став менше. Щоб нівелювати цю різницю між розмірами пікселів (а адже саме пікселями ми керуємо в CSS) з'явився параметр device-pixel-ratio (або dppx), який показує, скільки реальних екранних пікселів міститься в якомусь логічному пікселі, якими ми оперуємо в css. Наприклад, для дисплея IPhone 4 цей параметр дорівнює 2. Більш докладно можна прочитати на сайті W3C.

Припустимо, у нас є спрайт PNG зображень. У таких картинок фіксовані розміри. Якщо ми розмістимо такий спрайт на екрані IPhone 4, то кожен піксель спрайту буде розмитий на два екранних, а якщо розмазувати таку картинку на кількість пікселів в 2 рази більше, ніж розміри картинки, зображення буде виглядати жахливо.

Щоб позбутися цієї проблеми, можна використовувати зображення в 2 рази більшого розміру, при цьому розмір картинки в CSS задавати виходячи з розміру оригінального зображення (властивість background-size).

На даний момент існують екрани з dppx від 1 до 4 (скоро будуть і вище). Готувати спрайт для чотирьох розмірів екранів — це дуже багато роботи.

Виручає SVG. Векторний, не залежить від dppx-екрану, відмінно рендерится в сучасних (і не тільки) браузерах. Можна зробити тільки один розмір, і це зображення буде виглядати однаково на всіх екранах.

На жаль, SVG має кілька недоліків:
  • SVG погано відображає радіальні та інші складні градієнти (лінійні відображаються відмінно);
  • погано відображаються складні тіні;
  • не відображається в IE8.
Разом маємо два підходи: SVG для всього, чого можемо. Для решти готуємо PNG-зображення. Для IE8 будемо просто растеризувати SVG-зображення і готувати спрайт з них.

Щоб легко керувати цими підходами, були написані два чудових міксина (синтаксис SCSS):

@include bg-svg($svg image-name); для SVG-зображень;
@include bg($png image-name); для PNG зображень.


При цьому для IE8 у нас все сгенерируется і підключається автоматично, і png зображень сгенерируются media-запити, які підключають певні png картинки в залежності від типу екрану. Взагалі, для IE8 і IE9 генеруються окремі css-файли. Файли для IE8 створюються лише в тому випадку, якщо ми запустили складання з ключем --ie8.
Приклад використання миксинов:



Можете уявити за обсягом згенерованого коду, скільки роботи було зроблено автоматично.

Більш детально збірці графіки можна почитати в документації, а сам підхід відмінно описаний в презентації веб-розробника Тимофія Чаптыкова.

Користувальницькі таски
У TARS вже є все, що потрібно для розробки проектів будь-якої складності, але всім не догодиш. У кожного може бути якась своя специфіка, якісь додаткові завдання. Щоб вирішити цю проблему, був створений шаблон інтерфейсу тягаючи (tars/user-tasks/example-task.js). На його основі можна зробити свій таск, який легко вбудовується в існуючу інфраструктуру збирача.

Кожен таск за замовчуванням може видавати повідомлення про помилку або успішному виконанні, запускати перезавантаження сторінки в браузері і підключати інші таски, якщо необхідно зробити залежності між ними.

Оскільки основний package.json (файл, в якому знаходяться залежності скадальника) може змінюватися самим складальником (наприклад, при виконанні команди gulp update-deps), то користувальницькі залежно потрібно зберігати в окремому місці. Для цього є user-package.json. Синтаксис оголошення залежностей такий же, як і в основному package.json

Також є приклад інтерфейсу вотчера в директорії tars/user-watchers.

Плани на майбутнє
Є плани по додаванню нових фіч:
  • переїхати на Gulp 4 версії;
  • додати шаблонизаторы;
  • додати пре — і пост-процесорів для CSS;
  • додати підтримку ES6;
  • використовувати Browserify або webpack.
У найближчому майбутньому випустимо версію 1.3.0. Плани по випуску нових версій можна подивитися на GitHub.

Забув згадати, що це open source, тому чекаю ваших pull request'ів, питань щодо розширення функціоналу складальника в issue.

P. S.: 28-29 березня в Новосибірську пройде найбільша IT-конференція за Уралом — СodeFest. На цій конференції у TARS буде окремий стенд. Якщо приїдете на CodeFest — підходьте, задавайте питання.

Джерело: Хабрахабр

0 коментарів

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