Guide on how to use/import npm modules/packages in ClojureScript?

This is topic is created for SEO purpose. I asked this question many times during 2016 and 2017. And we got an answer since late 2017 with shadow-cljs. I’m still seeing other people asking the same question today.

The docs you want Shadow CLJS User’s Guide

Try running this project if you want to explore by yourself GitHub - minimal-xyz/minimal-shadow-cljs-importing-npm: Guide on importing npm module in ClojureScript with shadow-cljs

Guide

To run shadow-cljs, you need to install shadow-cljs from npm locally or globally, and add a shadow-cljs.edn as a configuration file. Nothing special here in the config(search “shadow-cljs guide” if you need more hints).

{:source-paths ["src"]
 :dev-http {8080 "target/"}
 :builds {:client {:output-dir "target/"
                   :asset-path "./"
                   :target :browser
                   :modules {:client {:init-fn app.main/main!}}
                   :devtools {:after-load app.main/reload!}}}}

Say I want to use several npm packages, I installed them from npm with yarn or npm:

yarn add dayjs shortid lodash

These libraries can be imported in JavaScript like:

import dayjs from "dayjs"

import shortid from "shortid"

import lodash from "lodash"
import {isString} from "lodash"

In ClojureScript, it’s almost same if you use shadow-cljs:

(ns app.main
  (:require ["dayjs"   :as dayjs]
            ["shortid" :as shortid]
            ["lodash"  :as lodash]
            ["lodash"  :refer [isString]]))

The code are being called in JavaScript like:

console.log(dayjs())

console.log(shortid.generate())

console.log(isString("a string"))
console.log(lodash.isObject("a string"))

It’s not much different. Onething to notice here is the syntax in lodash/isObject, which is using / rather than . since lodash has become a namespace in this file:

(.log js/console "dayjs" (dayjs))
(.log js/console "shortid" (.generate shortid))
(.log js/console "lodash" (isString :a-keyword) (lodash/isObject {}))

Again, you can more details on shadow-cljs docs Shadow CLJS User’s Guide

One more thing to mention is the example above runs in a browser. It should work in Node.js too since the libraries are platform-agnostic. However you need different shadow-cljs.edn configurations for :node-script, try this GitHub - minimal-xyz/minimal-shadow-cljs-nodejs: shadow-cljs hot code swapping for Node.js

More

  • CommonJS solution

Alternatively in shadow-cljs it’s also possible to compile ClojureScript to JavaScript files in CommonJS format, then you can just bundle them with Webpack or Parcel(maybe…). It worked. But running two bundling tools might be inconvenient. Read more in the topic: Beginner guide to compile ClojureScript to CommonJS and use Webpack - #2 by jiyinyiyong

  • Official solution

And you might also have found we can do that without shadow-cljs because of the official works in: New Guide: ClojureScript with Webpack - #17 by dnolen .

Well I’m just so glad I’m not trapped in the problem of using npm modules in ClojureScript any more. It was hard times between 2014 and 2017. Now we have solutions.

Please correct me I have mistakes in my code or maybe just send pull request on this. This guide probably need a review from @thheller.

15 Likes

:+1: for this SEO post (and kudos for adding the link to the new Webpack guide)

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.