Skip to content

dundalek/clojurescript-guide

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 

Repository files navigation

The Missing Guide for ClojureScript

When I started with ClojureScript and tried to follow the official Quick Start Guide it did not seem very straightforward to me. It is a good read though after a bit of hands on experience. This guide is a compilation of things I wished to know at the beginnings.

DISCLAIMER
I wrote down these notes as I was learning Clojure/Script in 2017. The tooling ecosystem changed significantly since then, but I did not manage to update the guide to reflect that. Here is the gist:

  • Clojure CLI is a better alternative to Leiningen
  • shadow-cljs is the best tool to compile ClojureScript replacing Fighweel, both for web and node.js apps
  • Babashka is a best runtime for scripting instead of Lumo

Quick Start

Try out some code using REPL.

Under node.js install Lumo with:

$ npm install -g lumo-cljs
$ lumo
cljs.user=> (println "hello clojure")
hello clojure

For Java first install Leiningen and then:

$ lein repl
user=> (+ 1 2)
3

Create a project

Node.js server or CLI app

Use cljs-node-app template: lein new cljs-node-app <project-name>

Compile the project: lein cljsbuild once main

Watch and recompile on changes: lein cljsbuild auto main

Web app

Use re-frame template which uses React.js via Reagent under the hood: lein new re-frame <project-name> +test +routes +aliases

Start development mode with live reload: lein dev

Compile the project: lein build

Documentation

Inside REPL:

;; Show function docs in REPL
(doc str)

;; Search in docs
(find-doc "reduce")

;; Show function source code
(source identity)

Browse API documentation and refer to Cheatsheet on the web.

Resources

Tutorials

Books

  • Programming Clojure by Stuart Halloway is a best book about Clojure for programmers, I recommend anyone learning Clojure(Script) to start with this one.
  • Clojure Applied: From Practice to Practitioner is a book focusing on more practical aspects of app development in Clojure. Includes chapters about domain modelling, managing state and application components.
  • Mastering Clojure describes in detail more advanced topics like paralelism, transducers, category theory, pattern matching and logic programming.

Explore other books by the community.

Exercises

Cookbook

Libraries

Opinionated list of useful libraries. There are alternatives but if you are just starting you can't go wrong by picking these.

Frontend

Check other libraries in Awesome ClojureScript list.

Backend

JS Interop

A great feature of ClojureScript is that you can work with native JS objects and use existing JS libraries.

;; Use js/ prefix for global names, e.g. to print in browser console
(js/console.log "Hello, world!")

;; Add dot to construct new objects
(js/Date. "2017-10-16") ; new Date("2017-10-16")

;; Call methods
(.toUpperCase s) ; s.toUpperCase()

;; Use treading macro to chain calls
(-> "BOOM" (.toLowerCase) (.slice 0 -1)) ; "BOOM".toLowerCase().slice(0, -1)

;; Access attributes
(.-length s) ; s.length

;; Nested attribute access
(.-location.href js/window) ; window.location.href
(aget window "location" "href") ; window["location"]["href"]

;; Set attributes
(aset obj "attr" "val") ; obj["attr"] = "val"

;; create native js objects with #js macro
#js {:a 1 :b 2} ; {a: 1, b: 2}
#js [1 2 3] ; [1, 2, 3]

;; convert cljs data structures into js objects
(clj->js obj)

;; convert js objects to cljs data structures
(js->clj obj :keywordize-keys true))

See a post with more details and comparison of JS and Clojure idioms.

Use node modules by seamlessly requiring them (starting with 1.9.854):

(ns example.core
  (:require [react :refer [createElement]]
            ["react-dom/server" :as ReactDOMServer :refer [renderToString]]))

(js/console.log (renderToString (createElement "div" nil "Hello World!")))

Some js libraries do not work with the compiler. In that case it is possible to bundle them with webpack. Or use externs: https://code.thheller.com/blog/shadow-cljs/2017/10/15/externs-the-bane-of-every-release-build.html Debug advanced compilation errors with :pseudo-names. Also try :infer-externs.

IO

To print at ClojureScript REPL

(println "Hello, world!")

Working with filesystem – require fs from node and call native functions.

(def fs (js/require "fs"))
(fs.readFileSync "foo.txt" "utf8")

When working in repl you can use slurp to read a file and spit to write a file.

;; Read a file into one long string
(def a-long-string (slurp "foo.txt"))

;; Write a long string out to a new file
(spit "foo.txt"
"A long
multi-line string.
Bye.")

Alternative approach is to use cljs-node-io which is a port of clojure.java.io.

EDN

EDN is to Clojure what JSON is to Javascript.

State

A state is the value of an identity at a point in time.

Changes to shared state:

  • Refs - coordinated synchronous
  • Atoms - uncoordinated synchronous
  • Agents - asynchronous
  • Vars - thread-local private - def, defn

Convention dynamic thread-wide bindings with asterisks *in* *out*.

Editor setup

Atom

Refer to this guide for a good setup. Essential packages are:

  • parinfer so that you don't have to worry about parentheses
  • proto-repl to evaluate code right within editor window

Spacemacs

  • Emacs distribution with Vim mode
  • Looks intriguing, it's on my list of things to try
  • Plugin for code refactoring: clj-refactor

Cursive

  • a great IDE based on IntelliJ

Debugging

Debug with Chrome DevTools

For more functionality use Dirac, a DevTools fork with additional ClojureScript related features.

Debug node apps with Chrome DevTools

  • Run node --inspect-brk build/main.js
  • In Chrome open chrome://inspect and select the session

Call tracing inside Atom

Use proto-repl: save call to record function calls and values of parameters, watch video with instructions.

General call tracing

Trace calls with Clairvoyant which is an alternative to clojure.tools.trace.

Tools

To use Leiningen plugins globally across projects put them in ~/.lein/profiles.clj, e.g.

{:user {:plugins [[lein-ancient "0.6.5"]
                  [lein-plz "0.4.0-SNAPSHOT" :exclusions [[rewrite-clj] [ancient-clj]]]]}}

List of Leiningen plugins

Packages management

  • lein search <pkg-name> – Search for packages
  • lein plz add <pkg-name> – Add package as dependency into project.clj
  • lein ancient – List outdated dependencies
  • lein ancient upgrade – Upgrade outdated dependencies
  • lein try – Try out Clojure libraries in a REPL without creating a project or adding them to an existing project.

Code quality

Code exploration

Documentation generators

Recommended:

  • cljdoc – documentation generator, includes hosting
  • codeina – api doc generator which is a nicer looking fork of codox
  • codox – with support for plugins and themes
  • marginalia – documentation showing description and code side by side in a literate programming style

Others:

Misc

CrossClj – Explore dependencies of Clojure packages among each other, see which function are called where and with what arguments:

JavaScript to ClojureScript translator

Bootstrapping:

  • calvin – A minimalistic build tool for ClojureScript projects that does not require the JVM
  • with Lumo

Articles about Lisp and Functional Programming:

About

My notes on ClojureScript

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published