This example shows how to load the re-resizable
npm module which provides a resizable React component. Requires the lein-npm plugin.
- Add the npm module to the :npm :dependencies section of
project.clj
:
:npm {:package {:scripts {:build "webpack -p"}}
:dependencies [[react "16.4.0"]
[react-dom "16.4.0"]
["@cljs-oss/module-deps" "1.1.1"]
+ [re-resizable "4.4.8"]
[browserify "15.1.0"]
[webpack "4.8.3"]]
:devDependencies [[express "4.16.3"]
[http-proxy-middleware "0.18.0"]
[tailwindcss "0.5.2"]
[postcss-cli "5.0.0"]
[cssnano "3.10.0"]
[glhd-tailwindcss-transitions "0.3.0"]
[minimist "1.2.0"]
[chalk "2.4.1"]
[webpack-cli "3.0.3"]]}
- Create a JavaScript source file to require all of your npm dependencies (we'll use
src/js/npm-deps.js
). Later we'll use a bundling tool likebrowserify
orwebpack
to bundle the modules for use in the browser. In this file, require the npm module and assign it to the browser'swindow
object. We need to give the module a name which we will refer to in the following steps; we'll useResizable
.
+ window.Resizable = require('re-resizable');
window.React = require('react');
window.ReactDOM = require('react-dom');
- Update the
:foreign-libs
section of the ClojureScript:compiler
sectionproject.clj
. We need to create a ClojureScript namespace to use in the context of a ClojureScriptrequire
block. We could just re-use the name of the npm module, but I prefer to avoid single-segment namespaces. I'll use the prefixnpm
and call itnpm.resizable
. Put the namespace into the:provides
section.
:compiler {:main foo.core
:output-to "resources/public/js/app.js"
:output-dir "resources/public/js/out"
:process-shim true
:foreign-libs [{:file "resources/public/js/npm-deps.js"
:provides ["cljsjs.react"
"cljsjs.react.dom"
"react"
"react-dom"
+ "npm.resizable"]
...
We also need to update the :global-exports
section to map the ClojureScript namespace we created in Step 3 to the JavaScript object we attached to the window object in Step 2.
:compiler {:main foo.core
:output-to "resources/public/js/app.js"
:output-dir "resources/public/js/out"
:process-shim true
:foreign-libs [{:file "resources/public/js/npm-deps.js"
:provides ["cljsjs.react"
"cljsjs.react.dom"
"react"
"react-dom"
"npm.resizable"]
:global-exports {react React
react-dom ReactDOM
+ npm.resizable Resizable}}]
- Now we can
require
the npm module into our ClojureScript application using this namespace. In this case there-resizable
npm module provides a React component:
(ns foo.auth.views
(:require [re-frame.core :refer [subscribe dispatch]]
[reagent.core :as reagent]
[clojure.string :as str]
[bouncer.core :as b]
[bouncer.validators :as v]
[camel-snake-kebab.core :refer [->kebab-case-keyword]]
[camel-snake-kebab.extras :refer [transform-keys]]
+ [npm.resizable :as resizable]))
...
+ [:> resizable {:defaultSize {:width 320 :height 200}
+ :class "bg-white" }
- Run
lein npm install
. This will install the npm dependencies. Use a tool likebrowserify
orwebpack
to bundle your modules for browser usage. The output will be the:foreign-libs
file declared above.
browserify example:
npm install browserify
./node_modules/.bin/browserify src/js/npm-deps.js -o resources/public/js/npm-deps.js
Next, compile your ClojureScript application using your normal workflow. Your npm module should now be available in your application.
- Declare externs for your module. If you're lucky, you can find an externs file for a recent version of your module at https://github.com/cljsjs/packages. For example here is one for React. Otherwise, you can use this externs generator. Basic steps are:
npm install -g externs-generator
Then run the generator on the foreign libs file resources/public/js/npm-deps.js
that was created in Step 5. You will need to specify a main interface to extern from your module. This can be a little tricky to determine, but read through the documentation for your module or look through the js source to see if you can figure it out. In our example it happens to be called Resizable
:
generate-extern -f resources/public/js/npm-deps.js -n Resizable -o externs.js
Specify the externs.js
file for the :externs
option to the ClojureScript compiler. If successful, you should be able to turn on advanced compilation and load the application in the browser without any errors. For more info see
https://github.com/cljsjs/packages/wiki/Creating-Externs