Integrating ClojureScript with JavaScript tooling
Tags: clojurescript, webpack
Published: 2020-04-25 19:28:39

---
title: Integrating ClojureScript with JavaScript tooling
published: true
description: 
tags: clojurescript, webpack
---

Recent [release](https://clojurescript.org/news/2020-04-24-release) of ClojureScript introduced [a new way](https://clojurescript.org/news/2020-04-24-bundle-target) to integrate with JavaScript tooling that makes it easier to import ClojureScript into existing JavaScript projects.

In this post we will explore how to setup and use these new features and integrate with bundlers such as Webpack.

First make sure you have [OpenJDK](https://openjdk.java.net/install/) installed and then install [Clojure CLI](https://clojure.org/guides/getting_started#_clojure_installer_and_cli_tools). Once that is done, it's time to create a project.

Create project folder and navigate to it
```shell
mkdir hello-bundler && cd hello-bundler
```

Create Clojure deps file with ClojureScript in dependencies
```shell
echo '{:deps {org.clojure/clojurescript {:mvn/version "1.10.741"}}}' > deps.edn
```

Install Webpack and React. We are going to use React in this guide since it is exclusively used in ClojureScript for building web apps.
```shell
yarn add webpack webpack-cli react react-dom --save-dev
```

Next create basic Clojure project structure and entry point namespace
```shell
mkdir -p src/hello_bundler
touch src/hello_bundler/core.cljs
```

Here we require `react` and `react-dom` installed in `node_modules`. Put the code below into `core.cljs`.
```clojure
(ns hello-bundler.core
  (:require [react]
            [react-dom]))

(def h1 (react/createElement "h1" nil "Hello!"))

(react-dom/render h1 (.getElementById js/document "root"))
```

Create ClojureScript build config file `build.edn` with the following contents
```clojure
{:main hello-bundler.core
 :output-to "out/index.js"
 :output-dir "out"
 :target :bundle
 :bundle-cmd {:none ["npx" "webpack" "--mode=development"]
              :default ["npx" "webpack"]}}
```

When building ClojureScript sources the compiler will output entry point file into `"out/index.js"` and then run Webpack build with a command provided in `:bundle-cmd` option.

Now create Webpack config which will consume ClojureScript's output. Make `webpack.config.js` with the following contents
```js
module.exports = {
  entry: "./out/index.js",
  output: {
    path: __dirname,
    filename: "bundle.js"
  }
}
```

Finally create `index.html` file in the root of the project which will load the final build artifact produced by Webpack.
```shell
echo '<div id="root"></div><script src="bundle.js"></script>' > index.html
```

And run ClojureScript build command
```shell
clj -m cljs.main -co build.edn --compile --repl
```

This will open your browser at [http://localhost:9000/](http://localhost:9000/) and start ClojureScript REPL in the terminal where you can evaluate ClojureScript code in browser's context, try this for example
```clojure
(js/alert "Hello!")
```

For a better interactive development experience you may want to connect to the REPL from your editor, for example here's a [plugin for VS Code](https://github.com/BetterThanTomorrow/calva).

## Production build
When building for production ClojureScript compiler will run a command specified in `:default` field in `:bundle-cmd`. To create production build and start a web server afterwards execute the following command.
```shell
clj -m cljs.main -co build.edn -O advanced --compile --serve
```

## Conclusion
With a new `:bundle` compiler target ClojureScript is able to produce JavaScript that can be consumed by tools like Webpack that in turn will take care of including NPM dependencies into the final bundle, so ClojureScript compiler doesn't have to reinvent the wheel here.

That also means that existing JavaScript projects can depend on ClojureScript code much easier now. In the next post we will explore how to consume ClojureScript code from JavaScript modules.