How to use node.js libraries and APIs with clojure ring?

398 Views Asked by At

Suppose there's an API that I want to use that's available in Node.js, but not for clojure ring. Is there a way I can use it in in clojure ring?

2

There are 2 best solutions below

0
On

If you want to use npm modules directly, your best bet is to use ClojureScript. ClojureScript is a Clojure library which compiles Clojure code to JavaScript. It provides seamless integration with Node.js. It goes without saying that you'll need to have both Node.js and NPM installed to allow for dependencies to be installed.

Depending on if you are using a deps.cljs file to configure your ClojureScript project, or using a build.clj file, you will need to add npm dependencies in one of the following ways:

  1. deps.cljs You need to add another key to the dependencies map:

    { ;;.. :npm-deps {"react" "15.4.2" "object-assign" "4.1.1"} ;; ... }

Then you should be able to use e.g. the dependency react as such:

(ns example.core
  (:require [react :refer [createElement]]))

(js/console.log (createElement "div" nil "Hello World!"))
  1. If using build.clj file, then your file will look something like this:

    (require '[cljs.build.api :as b])

    (b/build "src" {:output-dir "out" :output-to "out/main.js" :optimizations :none :main 'example.core :install-deps true :npm-deps {:react "15.6.1" :react-dom "15.6.1"}})

And you use the dependencies in the same way:

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

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

If you require further explanation, I encourage you to take a look at using JS modules in ClojureScript in general, the Enhanced Node.js Modules Support, an article about integrating Node modules, and a concise article that is kind of an excerpt from previous posts.

0
On

One general technique to use a library that's technologically or administratively incompatible with your program is to let it run as separate program (outside your Clojure app) and invoke it somehow.

If it's not too tightly coupled with the flow of your program, you could use Runtime.exec in place of the function call. There's also clojure.java.sh/sh.

With more effort, you could package the library as a web service to avoid a start-up cost per invocation (and gain flexibility to put it on a separate machine).