ClojureScript в современной веб-разработке

clojure-logo

Начнем с простого нехоливарного тезиса

Мы все делали неправильно!

            
              Project tree:

              |-- css
              |   `-- global.css
              |-- img
              |   |-- border.jpg
              |   |-- bg_top.gif
              |   `-- logo.jpg
              |-- js
              |   |-- jquery.js
              |   |-- prototype.js
              |   `-- myscript.js
              |-- html
              |   |-- contact.html
              |   |-- home.html
              |   `-- products.html
              `-- index.html
            
          

Так считаю не только я, но и эти ребята:

clojure-logo

clojure-logo

clojure-logo

Не нужно резать приложение по шву технологий

(js | css | html)!

jason

Его нужно резать на логические блоки

У каждого свой путь

Google - Web Components

Yandex - BEM + BEM-tools

Facebook - React + Flux

Не смотря на плюсы других решений, мы в свое время выбрали...

React.js

react-logo

При первом знакомстве код из tutorial'a React.js...

react-code

... вызывает такую реакцию!

my-eyes

Но это только сначала!

На самом деле React очень хорош

  1. Он уже сейчас позвоялет писать независимые компоненты
  2. Это всего лишь библиотека, а не framework! Его можно использовать в любом проекте
  3. Состояние компонентов неизменяемо (нельзя сделать так component.title = "Some new title"
  1. Состояние компонентов устанавливается явно! И это приводит к "реактивному" обновлению состояний дочерних элементов
  2. Функции в компонентах React.js - "практически" чистые (использование внешнего контекста сильно бъет по рукам). Они принимают данные и возвращают DOM (ну почти DOM)
  3. React.js - ОЧЕНЬ БЫСТРЫЙ!

Но у него есть один большой минус :( И имя ему...

JavaScript

js-logo

И тут на помощь нам приходит ClojureScript

js-logo

Плюсы ClojureScript

  1. Все приложение оптимизируется и минифицируется при помощи Google Closure Compiler
  2. Модульность, анонимные функции с удобным синтаксисом, персистентные структуры данных, иммутабельность из коробки
  3. Очень выразительный
  4. И конечно же...

... НЕРЕАЛЬНО КРУТОЙ REPL!!!

Заменим React.js и CSS на Reagent и Garden и получим независимый компонент

Начнем с Reagent'a

  1. Это практически тот же React.js
  2. Нет необходимости использывать XML в коде. Описываем HTML структурами данных ClojureScript
  3. Простой синтаксис
  4. Состояние приложения хранится в атомах, отдельно от компонетов. Мы можем обновлять состояние атомов, что влечет обновление компонентов, использующих данные атомы

Пример Reagent-компонента

          
            (ns example
              (:require [reagent.core :as reagent :refer [atom]]))
            (defn atom-input [value]
              [:input {:type "text"
                       :value @value
                       :on-change #(reset! value (-> % .-target .-value))}])

            (defn shared-state []
              (let [val (atom "foo")]
                (fn []
                  [:div
                   [:p "The value is now: " @val]
                   [:p "Change it here: " [atom-input val]]])))
          
        

Получаем это

Добавим немного стиля!

В этом нам поможет Garden

  1. Позволяет описывать CSS в том же стиле, что и Reagent
  2. Имеет возможность автоматической расстановки вендорных префиксов
  3. Данные - это код, а код - это данные. Мы можем реально программировать наш CSS :)
  4. Идеально сочетается с Reagent!

Пример использования Garden

          
            (css {:vendors ["webkit" "moz" "o"]}
               [[:.fn-simple-component {:color "#353535"}]
                [:.fn-simple-component-title
                 ^:prefix {:border-radius "10px"}
                 {:background-color "#f0f0f0"}
                 {:text-align "center"}
                 {:color "#353535"}
                 {:height "200px"}
                 {:padding "15px"}]]
          
        

А теперь объединим Reagent и Garden

          
            (ns frontend-new.components.simple-component
                (:require
                 [reagent.core :as reagent :refer [atom]]
                 [garden.core :refer [css]]
                 [frontend-new.common.css-helper :as css-helper :refer [include-css!]]))


            (include-css! "fn-simple-component" (css {:vendors ["webkit" "moz" "o"]}
                               [[:.fn-simple-component {:color "#353535"}]
                                [:.fn-simple-component-title
                                 ^:prefix {:border-radius "10px"}
                                 {:background-color "#f0f0f0"}
                                 {:text-align "center"}
                                 {:color "#353535"}
                                 {:height "200px"}
                                 {:padding "15px"}]]))

            (defn simple-component [title]
              [:div {:class "fn-simple-component"}
               [:h1 {:class "fn-simple-component-title"} title]])
          
        

Мы получили независимый компонент!

ic

Немного о REPL

Плюсы:

  • Код можно выполять не перезапуская проект (прямо наживую)
  • Постоянно имеем доступ к текущему состоянию приложения
  • Очень быстрый способ получить feedback на изменения в коде

Что для этого нужно:

  • В качестве редактора я использую Emacs
  • Связь с браузером обеспечивает Figwheel
  • Для хорошего REPL'a (и не только) я использую CIDER

DEMO TIME!

Задавайте вопросы, пожалуйста

Полезные сслыки

Мои контакты: