Logo

dev-resources.site

for different kinds of informations.

Setup shadow-cljs react project

Published at
4/2/2022
Categories
reagent
react
clojurescript
Author
maksimrv
Categories
3 categories in total
reagent
open
react
open
clojurescript
open
Author
8 person written this
maksimrv
open
Setup shadow-cljs react project

🚀 Create project

The first step is create a project

npx create-cljs-project my-project
Enter fullscreen mode Exit fullscreen mode

This command will create a project my-project with minimal required structure and install required dev dependencies for proper work of shadow-cljs

├── package-lock.json
├── package.json
├── shadow-cljs.edn
└── src
    ├── main
    └── test
Enter fullscreen mode Exit fullscreen mode

shadow-cljs.edn is a configuration file for ClojureScript project

;; shadow-cljs configuration
{:source-paths
 ["src/dev"
  "src/main"
  "src/test"]

:dependencies
 []

:builds
 {}}
Enter fullscreen mode Exit fullscreen mode

♺ Compile ClojureScript to JavaScript

Now, let’s create an entry point ClojureScript file

touch ./src/main/core.cljs
Enter fullscreen mode Exit fullscreen mode

and add minimal boilerplate code to it

;; ./src/main/core.cljs
(ns core)

(defn main []
  (js/console.log "Hello World!"))

(main)
Enter fullscreen mode Exit fullscreen mode

Now we should specify how to build the project. To do this, we should modify the :builds section in shadow-cljs.edn file

...

:builds
 {: **app** {:target : **browser**
        :modules {: **main** {:entries [**core**]}}}}}
Enter fullscreen mode Exit fullscreen mode
  • :app is a build id
  • :browser is target’s type for generated JavaScript files
  • :main is a name of generated JavaScript file
  • core is a ClojureScript entry namespace

You can add :output-dir "public/js" to explicitly specify output directory for generated files by default shadow-cljs will use public/js

Now we can compile our ClojureScript to JavaScript files

npx shadow-cljs compile **app**

shadow-cljs - config: /private/tmp/my-project/shadow-cljs.edn
shadow-cljs - connected to server
[:app] Compiling ...
[:app] Build completed. (43 files, 0 compiled, 0 warnings, 0.33s)
Enter fullscreen mode Exit fullscreen mode

đź‘ľ Start server

Now we are ready to setup the development server which will serve our static files. For this, we should return back to shadow-cljs.edn and add information about the dev server

:dev-http {8000 "public"}
Enter fullscreen mode Exit fullscreen mode
  • 8000 is a port which will be used by http server
  • public is a folder name for static files

Now we can start it by using watch command

npx shadow-cljs **watch** app
Enter fullscreen mode Exit fullscreen mode

Beside the start http server watchcommand also automatically recompile JavaScript files when we change ClojureScript one

You can open http://localhost:8000 and see that the server is running

Not found. Missing index.html.
Enter fullscreen mode Exit fullscreen mode

but complains on missing index.html. Let’s add index.html to the public folder

touch ./public/index.html
Enter fullscreen mode Exit fullscreen mode

and add some minimal markup with reference to our generated JavaScript file

<!DOCTYPE html>
<html lang="">
  <head>
    <title>my-project</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
  </head>
  <body>
    <div id="app"></div>
    <script src=" **js/main.js**" type="text/javascript"></script>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

If we open developer tools in the browser we should see “Hello World!” message in the browser’s console. You can open core.cljs file and change the message. Browser automatically pickup the change via embedded to shadow-cljs live update functionality and display the new message

📦 Add React as dependency

shadow-cljs support npm dependencies, so here we can install react via npm

npm install react
Enter fullscreen mode Exit fullscreen mode

Now we can use React in our ClojureScript application. Let’s print React’s version in the browser’s console. To do this, let’s modify core.cljs file

;; ./src/main/core.cljs
(ns core **(:require ["react" :as react])**)

(defn main []
  (js/console.log **(.-version react)**))

(main)
Enter fullscreen mode Exit fullscreen mode

We can look at the console without restarting the server and see that now it displays React version

[Log] shadow-cljs: load JS – "node_modules/react/index.js"
[Log] shadow-cljs: load JS – "core.cljs"
[Log] 17.0.2
Enter fullscreen mode Exit fullscreen mode

By the same way, we can install react-dom and render “Hello World!”

(ns core (:require 
           ["react" :as react]
           **["react-dom" :as react-dom]**))

(defn main []
  **(let [app-node (.getElementById js/document "app")]  
 (.render react-dom "Hello World!" app-node))** )

(main)
Enter fullscreen mode Exit fullscreen mode

🎸 Reagent

We can use raw react and react-dom in our ClojureScript but it’s much better and less verbose to use Reagent is a minimalistic ClojureScript interface for React.

Because Reagent is a ClojureScript module, we can’t install it via npm. To install it, we should define required version in shadow-cljs.edn

:dependencies
 [**[reagent "1.1.1"]**]
Enter fullscreen mode Exit fullscreen mode

Reagent is dependent from React & React DOM packages, so you still should install them via NPM.

Let’s update core.cljs code and replace React on Reagent

;; ./src/main/core.cljs
(ns core (:require 
          **[reagent.core :as r]  
 [reagent.dom :as rdom]** ))

**(defn app []  
 [:b "Hello World!"])**  

(defn main []
  (let [app-node (.getElementById js/document "app")]
    **(rdom/render [app] app-node)**))

(main)
Enter fullscreen mode Exit fullscreen mode
clojurescript Article's
30 articles in total
Favicon
Querido Yo del Futuro: Hoy intentaremos configurar una aplicaciĂłn fullstack en Clojure
Favicon
Why I chose Clojure/Script for building Vade Studio
Favicon
Converting JS Libraries to Clojure: Part 1
Favicon
Deploy your ClojureScript App to Cloudflare Workers
Favicon
shadow-cljs and running tests
Favicon
Giving new life to existing Om legacy SPAs with re-om
Favicon
Is Clojure the only language you need?
Favicon
Building an Application with ClojureScript
Favicon
How to Set up A Clojure Script and Phoenix Project
Favicon
How to create a library that works with Clojure and ClojureScript
Favicon
Setup shadow-cljs react project
Favicon
Logging readable ClojureScript (.cljs) errors to sentry!!
Favicon
How can I create a ClojureScript web app from scratch with Reagent and npm?
Favicon
Set up SSL/TLS for shadow-cljs https server
Favicon
ClojureScript on Cloudflare Workers
Favicon
Storybook.JS with Shadow-CLJS
Favicon
World Statistics Exercise
Favicon
The Pleasure of Clojure(Script): Part 1
Favicon
Using Specter on tree data structures in Clojure
Favicon
Clojure Re-Frame Exercise
Favicon
¿Por qué Clojure?
Favicon
Implementing the feed
Favicon
Try something new this week
Favicon
ClojureScript async MVU
Favicon
ClojureScript simple MVU loop
Favicon
Integrating ClojureScript with JavaScript tooling
Favicon
Understanding Transducers in JavaScript
Favicon
Casting visual spells with p5.js and ClojureScript, part 1
Favicon
ClojureScript REPL Workflow
Favicon
Developing, Testing and Deploying AWS Lambda Functions written in ClojureScript

Featured ones: