Экосистемный подход к сборке веб-проекта с TeaCSS

в 16:50, , рубрики: css, dsl, html, javascript, less, require, requirejs, sass, Веб-разработка, велосипед на ракетном топливе, метки: , , , , , , , , , ,

В этой статье я расскажу как можно организовать процесс сборки фронтэнда «от и до».

Советую начать со вводной статьи, если кто не читал.

Там я рассказывал про TeaCSS как про надмножество CSS, и это была неправда. Точнее – полуправда. И таким он был во времена своего создания (откуда и название).

Сейчас – это декларативный метаязык для генерации контента, во многом черпающий вдохновение из QML, Lisp, Clojure, Nemerle.

Предпосылки

Я бы для начала хотел договориться о некоторых базовых вещах, чтоб избежать холиваров:

  1. Тип или направленность языка не определяют его возможности, если язык Тьюринг-полный, то на нем можно сделать все, что угодно
  2. Тип языка и синтаксис определяют лишь удобство разработчика применительно к предметной области
  3. Для универсального применения императивные языки в целом подходят лучше т.к. оперируют с базовыми сущностями (строки, числа, структуры, классы) и из них, как из кирпичиков, позволяют строить дома.
  4. Для готовых предметных областей лучше (опять-таки, в целом) подходят декларативные языки т.к. процесс больше похоже не на строительство, а на настройку готовых сложных сущностей.

Именно из-за такого разделения «способностей» сейчас буйным цветом цветут различные сторонние 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 только они две также поддерживают минификацию и создание продакшен версии скриптов.

Но у них (скорее даже не у самих библиотек, а у самого подхода) есть ряд серьезных недостатков:

  1. Они смешивают систему сборки с кодом приложения, т.е. оставляют специфичные вызовы API сборки внутри продакшен кода. Для require вы должны особым образом оформлять ваш код. В Steal есть метод pluginify, но он попросту глючит и является попыткой вырезать при минифае Steal код из дев-версий файлов.
  2. Require не дружит с CSS
  3. Сама идея смешивать сборку и код подразумевает слабый контроль над сборкой или захламление кода. Это разные сущности и код, который собирает, обеспечивает модульность и т.п. вещи должен лежать отдельно от кода, который пойдет в конечную программу.
  4. 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

Заключение

TeaCSS – это мета-DSL декларативного толка, который изначально был придуман для облегчения разработки и сборки веб-приложений, но по сути является универсальным генератором контента на декларативной основе используя в качестве дружественного языка браузерный JS.

Это означает, что для запуска и работы не нужно ничего, кроме браузера, чтоб открывает возможность создавать интерактивный процесс разработки прямо в браузере.

Про это я расскажу в одной из следующих статей.

P.S.

Напомню, что я решил написать эту статью т.к. по сути делаю вещи очень похожие одновременно на последний проект Adobe — Brackets и на кикстартеровский Light-table. Но есть несколько отличий и мне кажется, что они могут быть ключевыми, чтоб рассказать про них, нужно начать с библиотеки, которая лежит в основе проекта — teacss. Надеюсь найти на хабре единомышленников и помощников/партнеров этот самый большой проект.

Автор: boomyjee

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js