SlideShare a Scribd company logo
Build tooling with Boot 
Juho Teperi / Metosin 
ClojuTRE 
25.11.2014
Contents 
• Example project 
• Challenges with Leiningen 
• Solutions using Boot 
• Summary
Example project 
• “(Typical) full-stack Clojure project” 
• src/clj, backend code 
• src/cljs 
• src/cljx, shared code 
• src/less (or sccs, garden etc.)
Leiningen 
• Configuration over code 
• Great with pure Clojure 
projects 
• Plugins provide additional 
tasks
Example project using Lein 
• Uses multiple lein plugins 
• lein cljx auto 
• lein cljsbuild auto (or figwheel) 
• lein less auto 
• lein repl 
• + unit tests 
• Several of these plugins watch for file changes 
• There are ways to combine all into one 
command
Lein, problem #1 
• Each lein command starts a JVM 
• Most commands fork another for the task 
• 7 JVMs 
• much GB 
• Slow start up
Lein, problem #2 
• Plugins are not composable 
• Descriptive configuration doesn’t help 
• Each lein plugin implements the file watching 
themselves 
• Each implementation works differently…
Lein, problem #3 
• Target directory is in effect a temporary 
directory 
• Lein uberjar 
• Uses different cljs compiler options 
• Probably uses same target path 
• First thing to try if you have problems: lein 
clean
:source-paths ["src/clj" "target/generated/clj"] 
:test-paths ["test/clj"] 
:cljsbuild {:builds {:app {:source-paths ["src/cljs" "target/generated/cljs"] 
:compiler {:output-to "resources/public/js/bootcamp.js" 
:output-dir "resources/public/js/out" 
:source-map "resources/public/js/out.js.map" 
:preamble ["react/react.min.js"] 
:externs ["react/externs/react.js"] 
:optimizations :none 
:pretty-print true}}}} 
:profiles {:dev {:plugins [[lein-figwheel "0.1.5-SNAPSHOT"] 
[lein-cljsbuild "1.0.3"] 
[com.keminglabs/cljx "0.4.0" :exclusions [org.clojure/clojure]]] 
:figwheel {:http-server-root "public" 
:port 3449 
:css-dirs ["resources/public/css"]} 
:cljx {:builds [{:rules :clj 
:source-paths ["src/cljx"] 
:output-path "target/generated/clj"} 
{:rules :cljs 
:source-paths ["src/cljx"] 
:output-path "target/generated/cljs"}]} 
:cljsbuild {:builds {:app {:source-paths ["dev-src/cljs"]}}}} 
+ This is missing e.g. uberjar 
settings for optimized cljs build
Boot (2) 
• Alternative build tool 
• Boot 1 is the old version 
• Boot 2 is the new one. It’s a significantly 
different as the old one. 
• Alpha 
• API changes are imminent etc. 
• Active development
Boot, solution #1 
• “Lein launches multiple JVMs and uses lots of memory” 
• All tasks run in the same JVM 
• Separate classloaders to prevent deps leaking 
• Btw. this is the same technique which is used by the app servers 
• Disclaimer: I have not tested the memory consumption.
Boot, solution #2 
• “Lein tasks are not composable, each plugin implements 
e.g. file watching themselves” 
• Tasks are functions 
• New tasks are composed from existing tasks 
using regular methods: comp 
• File watching is a task 
• Which can be composed together with other tasks
Boot, solution #3 
• “Dev and production tasks interfere because they use 
same directories” 
• Tasks create temporary directories as needed 
• Tasks use Boot API to find sources and publish their results 
• Cljx uses API to create temp dir, writes results to the dir... 
• Cljs asks for source files using the API -> sources include those 
written by cljx task 
• Processes don’t interfere with each other 
• running boot package to create production jar shouldn’t leave 
around files which break dev build 
• No need for clean-task
(set-env! 
:src-paths #{"src/clj" "src/cljs" "src/cljx"} 
:rsc-paths #{"resources"} 
:dependencies '[[adzerk/boot-cljs "0.0-2371-27"] 
[adzerk/boot-cljs-repl "0.1.6"] 
[adzerk/boot-reload "0.1.6"] 
[deraen/boot-cljx "0.1.0-SNAPSHOT"] 
… project deps … ]) 
(task-options! 
cljs [:output-to "public/main.js" 
:source-map true 
:unified true]) 
(deftask dev 
"Start the dev env..." 
[] 
(comp 
Global options 
● Watch: all following tasks run whenever there is file 
change. 
● cljs-repl, start-app are implemented so that they 
only run once. 
● (start-app is specific to the project) 
● cljs, cljx no-op if no file changes for them 
● Reload: Like figwheel. Sends websocket 
(watch) 
(cljs-repl) 
(cljx) 
(start-app) 
(cljs :optimizations :none) 
(reload :on-jsload 'saapas.core/main))) 
notifications to browser. 
(deftask dev-repl 
"Connect to the repl started by the dev task." 
[] 
(repl :client true))
Challenges with Boot 
• IDE Support 
• Editors using nrepl work (fireplace, cider) 
• Keep project.clj around for Cursive (and 
maybe others) 
• Missing tasks (less, unit testing…) 
• boot-cljx was easy to create, so should be 
the others
Summary 
Lein Boot 
Task envs Forks new JVMs Multiple classloaders in 
one JVM 
Configuration Configuration over 
code 
Composable functions 
Files Static classpath 
(target, resources) 
Tasks create temp dirs 
Equivalent JS tool Grunt Gulp, Broccoli
Questions?
Links 
• http://boot-clj.com/ 
• https://github.com/Deraen/saapas 
• #hoplon @ Freenode

More Related Content

More from Metosin Oy

More from Metosin Oy (13)

Fun with errors? - Clojure Finland Meetup 26.3.2019 Tampere
Fun with errors? - Clojure Finland Meetup 26.3.2019 TampereFun with errors? - Clojure Finland Meetup 26.3.2019 Tampere
Fun with errors? - Clojure Finland Meetup 26.3.2019 Tampere
 
Clojutre Real Life (2012 ClojuTRE Retro Edition)
Clojutre Real Life (2012 ClojuTRE Retro Edition)Clojutre Real Life (2012 ClojuTRE Retro Edition)
Clojutre Real Life (2012 ClojuTRE Retro Edition)
 
The Ancient Art of Data-Driven - reitit, the library -
The Ancient Art of Data-Driven - reitit, the library - The Ancient Art of Data-Driven - reitit, the library -
The Ancient Art of Data-Driven - reitit, the library -
 
Craft Beer & Clojure
Craft Beer & ClojureCraft Beer & Clojure
Craft Beer & Clojure
 
Performance and Abstractions
Performance and AbstractionsPerformance and Abstractions
Performance and Abstractions
 
ClojuTRE2016 Opening slides
ClojuTRE2016 Opening slidesClojuTRE2016 Opening slides
ClojuTRE2016 Opening slides
 
Schema tools-and-trics-and-quick-intro-to-clojure-spec-22.6.2016
Schema tools-and-trics-and-quick-intro-to-clojure-spec-22.6.2016Schema tools-and-trics-and-quick-intro-to-clojure-spec-22.6.2016
Schema tools-and-trics-and-quick-intro-to-clojure-spec-22.6.2016
 
ClojuTRE - a (very) brief history
ClojuTRE - a (very) brief historyClojuTRE - a (very) brief history
ClojuTRE - a (very) brief history
 
Wieldy remote apis with Kekkonen - ClojureD 2016
Wieldy remote apis with Kekkonen - ClojureD 2016Wieldy remote apis with Kekkonen - ClojureD 2016
Wieldy remote apis with Kekkonen - ClojureD 2016
 
ClojuTRE2015: Kekkonen - making your Clojure web APIs more awesome
ClojuTRE2015: Kekkonen - making your Clojure web APIs more awesomeClojuTRE2015: Kekkonen - making your Clojure web APIs more awesome
ClojuTRE2015: Kekkonen - making your Clojure web APIs more awesome
 
Clojure in real life 17.10.2014
Clojure in real life 17.10.2014Clojure in real life 17.10.2014
Clojure in real life 17.10.2014
 
Euroclojure2014: Schema & Swagger - making your Clojure web APIs more awesome
Euroclojure2014: Schema & Swagger - making your Clojure web APIs more awesomeEuroclojure2014: Schema & Swagger - making your Clojure web APIs more awesome
Euroclojure2014: Schema & Swagger - making your Clojure web APIs more awesome
 
Swaggered web apis in Clojure
Swaggered web apis in ClojureSwaggered web apis in Clojure
Swaggered web apis in Clojure
 

Recently uploaded

Search and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical FuturesSearch and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical Futures
Bhaskar Mitra
 

Recently uploaded (20)

Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
 
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMsTo Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
 
Knowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and backKnowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and back
 
Salesforce Adoption – Metrics, Methods, and Motivation, Antone Kom
Salesforce Adoption – Metrics, Methods, and Motivation, Antone KomSalesforce Adoption – Metrics, Methods, and Motivation, Antone Kom
Salesforce Adoption – Metrics, Methods, and Motivation, Antone Kom
 
Speed Wins: From Kafka to APIs in Minutes
Speed Wins: From Kafka to APIs in MinutesSpeed Wins: From Kafka to APIs in Minutes
Speed Wins: From Kafka to APIs in Minutes
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
 
Custom Approval Process: A New Perspective, Pavel Hrbacek & Anindya Halder
Custom Approval Process: A New Perspective, Pavel Hrbacek & Anindya HalderCustom Approval Process: A New Perspective, Pavel Hrbacek & Anindya Halder
Custom Approval Process: A New Perspective, Pavel Hrbacek & Anindya Halder
 
Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
 
In-Depth Performance Testing Guide for IT Professionals
In-Depth Performance Testing Guide for IT ProfessionalsIn-Depth Performance Testing Guide for IT Professionals
In-Depth Performance Testing Guide for IT Professionals
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
 
Demystifying gRPC in .Net by John Staveley
Demystifying gRPC in .Net by John StaveleyDemystifying gRPC in .Net by John Staveley
Demystifying gRPC in .Net by John Staveley
 
Unpacking Value Delivery - Agile Oxford Meetup - May 2024.pptx
Unpacking Value Delivery - Agile Oxford Meetup - May 2024.pptxUnpacking Value Delivery - Agile Oxford Meetup - May 2024.pptx
Unpacking Value Delivery - Agile Oxford Meetup - May 2024.pptx
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
 
When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...
 
How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...
 
"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi
 
Search and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical FuturesSearch and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical Futures
 
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptxIOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
 
Optimizing NoSQL Performance Through Observability
Optimizing NoSQL Performance Through ObservabilityOptimizing NoSQL Performance Through Observability
Optimizing NoSQL Performance Through Observability
 

ClojuTRE - Build tooling with Boot

  • 1. Build tooling with Boot Juho Teperi / Metosin ClojuTRE 25.11.2014
  • 2. Contents • Example project • Challenges with Leiningen • Solutions using Boot • Summary
  • 3. Example project • “(Typical) full-stack Clojure project” • src/clj, backend code • src/cljs • src/cljx, shared code • src/less (or sccs, garden etc.)
  • 4. Leiningen • Configuration over code • Great with pure Clojure projects • Plugins provide additional tasks
  • 5. Example project using Lein • Uses multiple lein plugins • lein cljx auto • lein cljsbuild auto (or figwheel) • lein less auto • lein repl • + unit tests • Several of these plugins watch for file changes • There are ways to combine all into one command
  • 6. Lein, problem #1 • Each lein command starts a JVM • Most commands fork another for the task • 7 JVMs • much GB • Slow start up
  • 7. Lein, problem #2 • Plugins are not composable • Descriptive configuration doesn’t help • Each lein plugin implements the file watching themselves • Each implementation works differently…
  • 8. Lein, problem #3 • Target directory is in effect a temporary directory • Lein uberjar • Uses different cljs compiler options • Probably uses same target path • First thing to try if you have problems: lein clean
  • 9. :source-paths ["src/clj" "target/generated/clj"] :test-paths ["test/clj"] :cljsbuild {:builds {:app {:source-paths ["src/cljs" "target/generated/cljs"] :compiler {:output-to "resources/public/js/bootcamp.js" :output-dir "resources/public/js/out" :source-map "resources/public/js/out.js.map" :preamble ["react/react.min.js"] :externs ["react/externs/react.js"] :optimizations :none :pretty-print true}}}} :profiles {:dev {:plugins [[lein-figwheel "0.1.5-SNAPSHOT"] [lein-cljsbuild "1.0.3"] [com.keminglabs/cljx "0.4.0" :exclusions [org.clojure/clojure]]] :figwheel {:http-server-root "public" :port 3449 :css-dirs ["resources/public/css"]} :cljx {:builds [{:rules :clj :source-paths ["src/cljx"] :output-path "target/generated/clj"} {:rules :cljs :source-paths ["src/cljx"] :output-path "target/generated/cljs"}]} :cljsbuild {:builds {:app {:source-paths ["dev-src/cljs"]}}}} + This is missing e.g. uberjar settings for optimized cljs build
  • 10. Boot (2) • Alternative build tool • Boot 1 is the old version • Boot 2 is the new one. It’s a significantly different as the old one. • Alpha • API changes are imminent etc. • Active development
  • 11. Boot, solution #1 • “Lein launches multiple JVMs and uses lots of memory” • All tasks run in the same JVM • Separate classloaders to prevent deps leaking • Btw. this is the same technique which is used by the app servers • Disclaimer: I have not tested the memory consumption.
  • 12. Boot, solution #2 • “Lein tasks are not composable, each plugin implements e.g. file watching themselves” • Tasks are functions • New tasks are composed from existing tasks using regular methods: comp • File watching is a task • Which can be composed together with other tasks
  • 13. Boot, solution #3 • “Dev and production tasks interfere because they use same directories” • Tasks create temporary directories as needed • Tasks use Boot API to find sources and publish their results • Cljx uses API to create temp dir, writes results to the dir... • Cljs asks for source files using the API -> sources include those written by cljx task • Processes don’t interfere with each other • running boot package to create production jar shouldn’t leave around files which break dev build • No need for clean-task
  • 14. (set-env! :src-paths #{"src/clj" "src/cljs" "src/cljx"} :rsc-paths #{"resources"} :dependencies '[[adzerk/boot-cljs "0.0-2371-27"] [adzerk/boot-cljs-repl "0.1.6"] [adzerk/boot-reload "0.1.6"] [deraen/boot-cljx "0.1.0-SNAPSHOT"] … project deps … ]) (task-options! cljs [:output-to "public/main.js" :source-map true :unified true]) (deftask dev "Start the dev env..." [] (comp Global options ● Watch: all following tasks run whenever there is file change. ● cljs-repl, start-app are implemented so that they only run once. ● (start-app is specific to the project) ● cljs, cljx no-op if no file changes for them ● Reload: Like figwheel. Sends websocket (watch) (cljs-repl) (cljx) (start-app) (cljs :optimizations :none) (reload :on-jsload 'saapas.core/main))) notifications to browser. (deftask dev-repl "Connect to the repl started by the dev task." [] (repl :client true))
  • 15. Challenges with Boot • IDE Support • Editors using nrepl work (fireplace, cider) • Keep project.clj around for Cursive (and maybe others) • Missing tasks (less, unit testing…) • boot-cljx was easy to create, so should be the others
  • 16. Summary Lein Boot Task envs Forks new JVMs Multiple classloaders in one JVM Configuration Configuration over code Composable functions Files Static classpath (target, resources) Tasks create temp dirs Equivalent JS tool Grunt Gulp, Broccoli
  • 18. Links • http://boot-clj.com/ • https://github.com/Deraen/saapas • #hoplon @ Freenode