Clojure Project Setup with create-cljs-app

In this chapter, we will bootstrap a project using create-cljs-app and understand the code generated. We'll also study Hiccup, a CLJS alternative for JSX, and various ways to require namespaces.

Project Source Code

Get the project source code below, and follow along with the lesson material.

Download Project Source Code

To set up the project on your local machine, please follow the directions provided in the README.md file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.

This lesson preview is part of the Tinycanva: Clojure for React Developers course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.

This video is available to students only
Unlock This Course

Get unlimited access to Tinycanva: Clojure for React Developers, plus 70+ \newline books, guides and courses with the \newline Pro subscription.

Thumbnail for the \newline course Tinycanva: Clojure for React Developers
  • [00:00 - 00:07] We have already learned how to set up shadow projects manually. We have also used first project for code examples in the last module.

    [00:08 - 00:21] Unlike first project, TinyKanwa will run in the browser instead of node terminal. So in order to get the repel working, we will need to open the app in a browser in place of running node script in the shell.

    [00:22 - 00:31] Starting with this chapter, we request you to follow along with the lesson text . The videos will give you an overview of the steps and explain new concepts.

    [00:32 - 00:44] But the actual build process is text only. In this chapter, we will set up a new shadow project, learn about hiccup and the require syntax and ultimately start the dev repel.

    [00:45 - 00:55] You can use create cljs app to scaffold a new project. Once your project is ready, open it up in an editor of your choice so we can study the configuration.

    [00:56 - 01:14] By default, we have four builds, a development server configured to run on port 3000, serving contents from the public directory, an N-repell server configured on port 3333 and one source path SRC. We also have two dependencies that we will learn about in detail soon.

    [01:15 - 01:27] Reagent is a minimalist closure wrapper for re-hat and dev card is a storybook like tool for developing components in isolation. Because of now, we should only be concerned with the app build target.

    [01:28 - 01:38] The app is configured to call app.code/main function on startup. It targets the browser runtime and spits the compiled JavaScript code to public /js folder.

    [01:39 - 01:47] Let's check the main function definition. As we learned before, the function defined as iNet fn is called as soon as the app is ready.

    [01:48 - 01:59] The generated app.code namespace might look a little different from the names paces and functions we have defined so far. The NS definition accepts a documentation string just like function definition.

    [02:00 - 02:12] The required form can be passed to NS definition along with vectors of names paces needed. We load reagent code namespace and alias it as R and then the app hello namespace.

    [02:13 - 02:19] App.hello is defined in SRCAppHello.CLGS. This namespace holds the definition for the hello function.

    [02:20 - 02:30] This function was generated by createCLGSApp and is the reagent version of a functional component. Like React uses JSX to define components, reagent uses hiccup.

    [02:31 - 02:41] Hiccup and JSX can be translated seamlessly. Element open and close tags are replaced with vectors and props are replaced with prop maps.

    [02:42 - 02:52] All we need to know right now is that the app.code/main function is the entry point of this app. Third party's library defines their custom namespaces that you can require.

    [02:53 - 02:57] In the example above we require reagent code. There are multiple ways to do so.

    [02:58 - 03:12] The simplest way is to just require the namespace. For example if we require foo bar, any variable or function defined in this namespace will be available to the namespace where you required it as foo.bar/bars.

    [03:13 - 03:21] Typing the entire namespace might be cumbersome so you can define aliases too like we did with reagent code. This can be achieved using the as form.

    [03:22 - 03:34] It is also possible to require only a subset of the namespace. For example if we want just the bars definition from foo.bar namespace you can use the refer keyword.

    [03:35 - 03:45] The refer and the ask keyword can be used in conjunction as well. Shadow provides us with two special require forms that helps interoperate with npm.

    [03:46 - 03:56] We can require npm package as npm package. Notice the string around the first form and we can also refer to parts of the package using the refer keyword.

    [03:57 - 04:10] To require parts of a closure namespace with refer keyword we use square brackets but to require parts of a package from an npm package we use parenthesis. The main function is familiar to what we have learned so far.

    [04:11 - 04:24] It interrupts with JavaScript to find DOM element with ID app and then calls re agents render method with DOM element and the hello component. The carrot dev afterload denotes metadata attached to a function.

    [04:25 - 04:35] In this case the metadata is to let shadow know that the render function should be called each time the app is hot reloaded. Dev afterload keyword is a shadow lifecycle look.

    [04:36 - 04:44] In production compilation shadow minifies and uglyifies your code. Uglification renames variables and function definitions.

    [04:45 - 04:53] But we need the main function to stay intact so it can be called when the uploads. Functions mark fit export are not ugly or renamed.

    [04:54 - 05:03] Create CLGS app creates a same package JSON as well. It adds React as a dependency and also defines scripts to run, test and package the application.

    [05:04 - 05:10] You can inspect package JSON and analyze all scripts. But for now we only care about the start and the build script.

    [05:11 - 05:20] Start starts the application in dev mode and build compiles the application in production mode. Our first project was a node script and could be executed in a terminal.

    [05:21 - 05:30] But the code produced via browser target needs a web browser to run. The public directory contains files that will be served to a browser via a development server.

    [05:31 - 05:39] The index.html file loads the compile script. It also defines a div fit ID of app which is used by render function to render the react application.

    [05:40 - 05:47] The public directory also has a top level style sheet. Other assets like fonts, images etc can also be placed here.

    [05:48 - 05:53] The bootstrap project has some other files related to testing as well. But we will explore them later.

    [05:54 - 06:03] For now we can jump straight to starting a wrap using yarn start. After the build is completed you would see a react component running on local host 3000.

    [06:04 - 06:14] In this chapter we created a react reagent application using create cljs app. We walked through some components that were automatically generated and started the application.

    [06:15 - 06:20] We also saw how DEFIN can be used with metadata and learnt about hiccup and require forms.