В этой статье я расскажу как можно организовать процесс сборки фронтэнда «от и до».
Советую начать со вводной статьи, если кто не читал.
Там я рассказывал про TeaCSS как про надмножество CSS, и это была неправда. Точнее – полуправда. И таким он был во времена своего создания (откуда и название).
Сейчас – это декларативный метаязык для генерации контента, во многом черпающий вдохновение из QML, Lisp, Clojure, Nemerle.
Предпосылки
Я бы для начала хотел договориться о некоторых базовых вещах, чтоб избежать холиваров:
- Тип или направленность языка не определяют его возможности, если язык Тьюринг-полный, то на нем можно сделать все, что угодно
- Тип языка и синтаксис определяют лишь удобство разработчика применительно к предметной области
- Для универсального применения императивные языки в целом подходят лучше т.к. оперируют с базовыми сущностями (строки, числа, структуры, классы) и из них, как из кирпичиков, позволяют строить дома.
- Для готовых предметных областей лучше (опять-таки, в целом) подходят декларативные языки т.к. процесс больше похоже не на строительство, а на настройку готовых сложных сущностей.
Именно из-за такого разделения «способностей» сейчас буйным цветом цветут различные сторонние DSL (Domain Specific Language), встроенные в язык DSL (в руби, лисп и т.д.) декларативного толка. На них удобно описывать процессы сборки, тестирования, интерфейсы, внешний вид – т.е. все, где базовая сущность уже определена. Для приведенных примеров сущности – это «проект», «функциональность», «пользовательский ввод и поведение программы» и «типаж предмета, чей внешний вид описывается».
Что же такое TeaCSS
Это каркас для декларативных DSL, конструктор компиляторов с Javascript API. И несколько базовых реализаций DSL для стилей, скриптов, шаблонов и изображений из коробки.
Он берет на себя парсинг, оказывает существенную помощь в генерации контента. Чем-то этот проект родственнен PEG.js и Jison – если есть время, рекомендую ознакомиться.
И если есть желание, то могу написать статью про парсеры и компиляторы, если это кому-то нужно.
Синтаксис у TeaCSS прост до безобразия:
[Язык] Блочное_Правило {
// комментарий
/* многострочный комментарий */
@import "another_tea_file.tea";
@ строчка JS
@{ многострочный JS }
[Язык] Правило;
[Язык] Блочное_правило {
// и так далее, сколько угодно уровней вложенности
}
}
Он такой именно потому, что практически любой декларативный язык можно описать как набор вложенных правил, а встроенный JS позволяет добавлять императивные элементы в язык, такие как переменные, условия, циклы и прочее.
Например, чтоб описать LESS-подобный язык для стилей достаточно всего 150 строк кода.
github.com/boomyjee/teacss/blob/master/src/teacss/core.js#L309
Именно он и являетc языком генерации по умолчанию (Style).
Чтоб переключиться на другой язык достаточно начать селектор с него:
SomeLang {
// правила специфичные для этого языка
}
TeaCSS как система сборки
Второй встроенный язык в teacss – это Script, как несложно догадаться, он служит для сборки скриптов приложения.
Синтаксис у него простой:
Script some_name {
@append "some/script/path.js";
@append {
function bla() { /* … */ } // Some javascript Code
}
}
Т.е. линейные элементы – это просто сторонние скрипты, блочные – просто код, который вы не хотите выделять отдельно. В продакшене все скрипты будут объединены по some_name, т.е. вы можете сгруппировать JS, как вам удобно.
Сама библиотека TeaCSS собирается сама собой, вот ее «мейкфайл»:
github.com/boomyjee/teacss/blob/master/src/build.tea
При таком подходе TeaCSS является заменой библиотек для модульной разработки и экосистемой для сборки фасада веб-приложений.
Он берет на себя то, что делают RequireJS или StealJS.
Я привел как пример именно эти 2 библиотеки потому, что AFAIK только они две также поддерживают минификацию и создание продакшен версии скриптов.
Но у них (скорее даже не у самих библиотек, а у самого подхода) есть ряд серьезных недостатков:
- Они смешивают систему сборки с кодом приложения, т.е. оставляют специфичные вызовы API сборки внутри продакшен кода. Для require вы должны особым образом оформлять ваш код. В Steal есть метод pluginify, но он попросту глючит и является попыткой вырезать при минифае Steal код из дев-версий файлов.
- Require не дружит с CSS
- Сама идея смешивать сборку и код подразумевает слабый контроль над сборкой или захламление кода. Это разные сущности и код, который собирает, обеспечивает модульность и т.п. вещи должен лежать отдельно от кода, который пойдет в конечную программу.
- Steal не позволяет гибко настроить конечные пути к ресурсам и нет никакого (кроме ручного копания в минифаеном скрипте) пути это перенастроить.
Поэтому сразу напрашивается правила сборки выделять в отдельное место (в C разработке — это мейкфайл).
Роль такого мейкфайла и берет на себя teacss.Script.
Подход к использованию тот же самый.
<? if ($applicationMode=="development") ?>
<link tea="scripts.tea">
<script src="teacss.js"></script>
<? else ?>
<script src="production.js">
<? endif ?>
Подключение других языков и несколько примеров
TeaCSS сам по себе – модульная и расширяемая система сборки. Чтоб подключить новый язык на основе базового синтаксиса достаточно добавить импорт с описанием языка.
Например:
@import "some_language_definition.js";
@import "some_tea_file.tea"; // внутри этого файла уже будет доступен новый язык
Про то, как описать новый язык в экосистеме TeaCSS, я напишу отдельную статью. А пока покажу пример такого языка.
TeaCSS может быть использован как система генерации статических сайтов, аналоги – Jekyll и вот списком, много iwantmyname.com/blog/2011/02/list-static-website-generators.html
Синтаксис интуитивно понятный, при этом есть поддержка компиляции в Liquid.
Template layout {
html {
head {
meta[http-equiv="Content-Type"][content="text/html; charset=utf-8"];
title TeaCSS;
}
body {
#header {
.item(url,text) {
% if path == "@{url}" {
a.active[href="@{url}"] @text;
}
% else {
a[href="@{url}"] @text;
}
}
div {
.item('index.htm','Intro');
.item('canvas.htm','Canvas');
a[href="download.htm"][target="_blank"] Download;
}
}
#content {
% block content {}
}
}
}
}
Это, используется, например, чтоб сгенерировать сайт teacss.org.
Вот репозиторий в котором лежит сам сайт и его генератор — github.com/boomyjee/teacss-docs
И более развернутый пример — github.com/boomyjee/teacss-docs/blob/master/build/templates/pages/index.tea
В качестве вспомогательного языка используются конструкции вроде
Highlight xml {
<link tea="style.tea">
<script src="teacss.js"></script>
}
Которые дают на выходе html для подсвеченного кода.
Я сделал небольшой плейграунд, чтоб вы могли подробнее посмотреть, как работает генерация html – teacss.org/template.htm
Заключение
TeaCSS – это мета-DSL декларативного толка, который изначально был придуман для облегчения разработки и сборки веб-приложений, но по сути является универсальным генератором контента на декларативной основе используя в качестве дружественного языка браузерный JS.
Это означает, что для запуска и работы не нужно ничего, кроме браузера, чтоб открывает возможность создавать интерактивный процесс разработки прямо в браузере.
Про это я расскажу в одной из следующих статей.
P.S.
Напомню, что я решил написать эту статью т.к. по сути делаю вещи очень похожие одновременно на последний проект Adobe — Brackets и на кикстартеровский Light-table. Но есть несколько отличий и мне кажется, что они могут быть ключевыми, чтоб рассказать про них, нужно начать с библиотеки, которая лежит в основе проекта — teacss. Надеюсь найти на хабре единомышленников и помощников/партнеров этот самый большой проект.
Автор: boomyjee