Уже больше года я знакомлюсь с Clojure, и чем больше я в него погружаюсь, тем больше он становится языком . Как только вы победите «страх скобок», все остальное будет иметь значение: инструменты, сообщество, хорошие инженерные практики. Настало время убедить других. В этой статье я попытаюсь пройтись по простому веб-приложению с нуля, чтобы показать ключевые инструменты и библиотеки, которые использовались для разработки с Clojure в конце 2015 года.
Примечание для Clojurians : Этот материал довольно прост и может быть полезен для вас, если вы уже немного знаете Clojure, но никогда не делали ничего большего, чем приложение hello world.
Примечание для разработчиков Java : этот материал показывает, как заменить Spring, Angular, grunt, live-reload набором инструментов и библиотек Clojure и небольшим количеством кода.
- Репо с финальным кодом и отдельными шагами здесь .
начальная загрузка
Я думаю, что все согласились с тем, что этот компонент является отраслевым стандартом для управления жизненным циклом приложений Clojure. Если вы являетесь разработчиком Java, вы можете думать об этом как о замене Spring (DI) — вы объявляете зависимости между «компонентами», которые разрешаются при «системном» запуске. Поэтому вы просто говорите: «Моему компоненту нужен пул хранилища / базы данных», а библиотека компонентов «внедряет» его для вас.
Для простоты я хотел бы начать с шаблона веб-приложения воздуховодов . Это хорошее приложение для начинающих компонентов, основанное на 12-факторной философии. Итак, начнем с этого:
lein new duct clojure-web-app +example
Параметр +example
указывает duct создать пример конечной точки с маршрутами HTTP — это было бы полезно. Чтобы завершить загрузку, запустите lein setup
clojure-web-app
.
Хорошо, давайте углубимся в код. Код, связанный с компонентами и инъекциями, должен находиться в файле system.clj
:
01
02
03
04
05
06
07
08
09
10
|
(defn new -system [config] (let [config (meta-merge base-config config)] (-> (component/system-map :app (handler-component (:app config)) :http (jetty-server (:http config)) :example (endpoint-component example-endpoint)) (component/system-using {:http [:app] :app [:example] :example []})))) |
В первом разделе вы создаете экземпляры компонентов без зависимостей, которые разрешаются во втором разделе. Таким образом, в этом примере для компонента «http» (сервера) требуется «приложение» (абстракция приложения), которое, в свою очередь, внедряется с «примером» (фактические маршруты). Если вашему компоненту нужны другие, вы можете получить их по именам (а именно: по ключевым словам Clojure).
Чтобы запустить систему, вы должны запустить REPL — интерактивную среду, работающую в контексте вашего приложения:
lein repl
После просмотра подсказки наберите (go)
. Приложение должно запуститься, вы можете посетить http: // localhost: 3000, чтобы увидеть пример страницы.
Огромным преимуществом использования компонентного подхода является то, что вы получаете полностью перезагружаемое приложение. Когда вы изменяете буквально все что угодно — конфигурацию, конечные точки, реализацию, вы можете просто набрать (reset)
в REPL, и ваше приложение будет обновлено с помощью кода. Это особенность языка, никакой JRebel, Spring-reloaded не требуется.
Добавление конечной точки REST
Хорошо, на следующем шаге давайте добавим некоторую базовую конечную точку REST, возвращающую JSON. Нам нужно добавить 2 зависимости в файл project.clj
:
1
2
3
4
|
:dependencies ... [ring/ring-json "0.3.1" ] [cheshire "5.1.1" ] |
Ring-json добавляет поддержку JSON для ваших маршрутов (в кольце это называется промежуточным программным обеспечением), а cheshire — это анализатор Clojure JSON (как Jackson в Java). Изменение проектных зависимостей, если это одна из немногих задач, требующих перезапуска REPL, поэтому нажмите CTRL-C и снова введите lein repl
.
Чтобы настроить промежуточное программное обеспечение JSON, мы должны добавить wrap-json-body
и wrap-json-response
непосредственно перед wrap-defaults
в system.clj
:
1
2
3
4
5
6
7
8
9
|
(:require ... [ring.middleware.json :refer [wrap-json-body wrap-json-response]]) (def base-config {:app {:middleware [[wrap-not-found :not-found] [wrap-json-body {:keywords? true }] [wrap-json-response] [wrap-defaults :defaults]] |
И, наконец, в endpoint/example.clj
мы должны добавить некоторый маршрут с ответом JSON:
1
2
3
4
5
6
7
8
|
(:require ... [ring.util.response :refer [response]])) (defn example-endpoint [config] (routes (GET "/hello" [] (response {:hello "world" })) ... |
Перезагрузите приложение с помощью (reset)
в REPL и протестируйте новый маршрут с помощью curl
:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
curl -v http: //localhost:3000/hello < HTTP/ 1.1 200 OK < Date: Tue, 15 Sep 2015 21 : 17 : 37 GMT < Content-Type: application/json; charset=utf- 8 < Set-Cookie: ring-session=37c337fb-6bbc-4e65-a060-1997718d03e0;Path=/;HttpOnly < X-XSS-Protection: 1 ; mode=block < X-Frame-Options: SAMEORIGIN < X-Content-Type-Options: nosniff < Content-Length: 151 * Server Jetty( 9.2 . 10 .v20150310) is not blacklisted < Server: Jetty( 9.2 . 10 .v20150310) < * Connection # 0 to host localhost left intact { "hello" : "world" } |
Оно работает! В случае каких-либо проблем вы можете найти рабочую версию в этом коммите .
Добавление внешнего интерфейса с figwheel
Кодирование бэкенда в Clojure великолепно, но как насчет внешнего интерфейса? Как вы, возможно, уже знаете, Clojure можно скомпилировать не только в байт-код JVM, но и в Javascript. Это может показаться знакомым, если вы использовали, например, Coffeescript. Однако философия ClojureScript заключается не только в том, чтобы обеспечить некоторый синтаксический сахар, но и в улучшении вашего цикла разработки с помощью великолепных инструментов и полностью интерактивной разработки. Посмотрим, как этого добиться.
Лучший способ представить ClojureScript в проекте — это figweel . Сначала давайте добавим плагин и конфигурацию Fighweel в project.clj
:
1
2
3
|
:plugins ... [lein-figwheel "0.3.9" ] |
И конфигурация cljsbuild:
1
2
3
4
5
6
7
8
|
:cljsbuild {:builds [{:id "dev" :source-paths [ "src-cljs" ] :figwheel true :compiler {:main "clojure-web-app.core" :asset-path "js/out" :output-to "resources/public/js/clojure-web-app.js" :output-dir "resources/public/js/out" }}]} |
Вкратце это говорит компилятору ClojureScript, что нужно взять исходники из src-cljs
с поддержкой figweel
и поместить полученный JavaScript в файл resources/public/js/clojure-web-app.js
. Поэтому нам нужно включить этот файл в простую HTML-страницу:
1
2
3
4
5
6
7
8
9
|
<!DOCTYPE html> <head> </head> <body> <div id= "main" > </div> <script src= "js/clojure-web-app.js" type= "text/javascript" ></script> </body> </html> |
Для обслуживания этого статического файла нам нужно изменить некоторые значения по умолчанию и добавить соответствующий маршрут. В system.clj
измените api-defaults
на site-defaults
как в разделе require, так и в функции base-config
. В example.clj
добавьте следующий маршрут:
1
|
(GET "/" [] (io/resource "public/index.html" ) |
Снова (reset)
в окне REPL следует перезагрузить все.
Но где наш исходный файл ClojureScript? Давайте создадим файл core.cljs
в core.cljs
src-cljs/clojure-web-app
:
1
2
3
4
5
|
(ns ^:figwheel-always clojure-web-app.core) (enable-console-print!) (println "hello from clojurescript" ) |
Откройте другой терминал и запустите lein fighweel
. Он должен скомпилировать ClojureScript и вывести «Prompt покажет, когда figwheel подключится к вашему приложению». Откройте http://localhost:3000
. Окно Fighweel должно подсказать:
1
2
|
To quit, type: :cljs/quit cljs.user=> |
Тип (js/alert "hello")
. Boom! Если все работает, вы должны увидеть и предупредить в своем браузере. Откройте консоль разработчика в вашем браузере. Вы должны увидеть hello from clojurescript
напечатанного на консоли. Измените его в core.cljs
на (println "fighweel rocks")
и сохраните файл. Без перезагрузки страницы вы должны увидеть обновленное сообщение. Figweel скалы! Опять же, в случае каких-либо проблем, обратитесь к этой фиксации .
В следующем посте я покажу, как извлекать данные из MongoDB, обрабатывать их с помощью REST для более широкого использования и писать компоненты ReactJs / Om для их визуализации. Будьте на связи!
Ссылка: | Веб-разработка Clojure — состояние от нашего партнера JCG Петра Ягельского в блоге Full JVM по разработке стека… |