SlideShare a Scribd company logo
1 of 18
Download to read offline
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

TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
TrustArc
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
Tales from a Passkey Provider Progress from Awareness to Implementation.pptx
Tales from a Passkey Provider  Progress from Awareness to Implementation.pptxTales from a Passkey Provider  Progress from Awareness to Implementation.pptx
Tales from a Passkey Provider Progress from Awareness to Implementation.pptx
FIDO Alliance
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Victor Rentea
 

Recently uploaded (20)

Choreo: Empowering the Future of Enterprise Software Engineering
Choreo: Empowering the Future of Enterprise Software EngineeringChoreo: Empowering the Future of Enterprise Software Engineering
Choreo: Empowering the Future of Enterprise Software Engineering
 
Modernizing Legacy Systems Using Ballerina
Modernizing Legacy Systems Using BallerinaModernizing Legacy Systems Using Ballerina
Modernizing Legacy Systems Using Ballerina
 
Quantum Leap in Next-Generation Computing
Quantum Leap in Next-Generation ComputingQuantum Leap in Next-Generation Computing
Quantum Leap in Next-Generation Computing
 
Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..
 
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
 
WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...
WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...
WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Navigating Identity and Access Management in the Modern Enterprise
Navigating Identity and Access Management in the Modern EnterpriseNavigating Identity and Access Management in the Modern Enterprise
Navigating Identity and Access Management in the Modern Enterprise
 
Design and Development of a Provenance Capture Platform for Data Science
Design and Development of a Provenance Capture Platform for Data ScienceDesign and Development of a Provenance Capture Platform for Data Science
Design and Development of a Provenance Capture Platform for Data Science
 
Tales from a Passkey Provider Progress from Awareness to Implementation.pptx
Tales from a Passkey Provider  Progress from Awareness to Implementation.pptxTales from a Passkey Provider  Progress from Awareness to Implementation.pptx
Tales from a Passkey Provider Progress from Awareness to Implementation.pptx
 
AI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by AnitarajAI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by Anitaraj
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontology
 
Intro to Passkeys and the State of Passwordless.pptx
Intro to Passkeys and the State of Passwordless.pptxIntro to Passkeys and the State of Passwordless.pptx
Intro to Passkeys and the State of Passwordless.pptx
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
API Governance and Monetization - The evolution of API governance
API Governance and Monetization -  The evolution of API governanceAPI Governance and Monetization -  The evolution of API governance
API Governance and Monetization - The evolution of API governance
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptx
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 

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