Edited at

ClojureScript内からnpmモジュールを呼び出す(npm-deps)

More than 1 year has passed since last update.


tl;dr

project.clj にコンパイラ・オプション :npm-deps:install true を追加。

こんな感じ。

diff --git a/project.clj b/project.clj

index 24f0146..065a9f6 100644
--- a/project.clj
+++ b/project.clj
@@ -25,6 +25,8 @@
:output-to "target/js/compiled/hello_aws_cli.js"
:output-dir "target/js/compiled/dev"
:target :nodejs
+ :npm-deps {:aws-sdk "^2.167.0"}
+ :install-deps true
:optimizations :none
:source-map-timestamp true}}
{:id "prod"


ClojureScriptを書き始めたcljs newbieがハマる大きな落とし穴、

それが「ClojureScriptコード内からnpmなコードを呼び出す」です。1

ちょっとググってみたところ、CLJSJSを使うといいよ〜とか、そこにない場合は自力でexternsを書く必要があるよとか、いろいろ見つかるのですが、どれもうまく行かなかったり設定に戸惑ったりすること1週間...2


npm-deps コンパイラ・オプションを使え!

そんな中、この記事を発見。

https://clojurescript.org/news/2017-07-12-clojurescript-is-not-an-island-integrating-node-modules

ほうほう!

早速試してみましょう。

$ lein new figwheel-node hello-aws-cli

$ cd hello-aws-cli

project.clj に :npm-deps {:aws-sdk "^2.167.0"}:install trueを追加。

diff --git a/project.clj b/project.clj

index 24f0146..065a9f6 100644
--- a/project.clj
+++ b/project.clj
@@ -25,6 +25,8 @@
:output-to "target/js/compiled/hello_aws_cli.js"
:output-dir "target/js/compiled/dev"
:target :nodejs
+ :npm-deps {:aws-sdk "^2.167.0"}
+ :install-deps true
:optimizations :none
:source-map-timestamp true}}
{:id "prod"

依存関係インストール + cljsコード → JSコードへのトランスパイル + REPLを開くために lein figwheelを実行。

$ lein figwheel

Launching ClojureScript REPL for build: dev
Figwheel Controls:
(stop-autobuild) ;; stops Figwheel autobuilder
(start-autobuild [id ...]) ;; starts autobuilder focused on optional ids
(switch-to-build id ...) ;; switches autobuilder to different build
(reset-autobuild) ;; stops, cleans, and starts autobuilder
(reload-config) ;; reloads build config and resets autobuild
(build-once [id ...]) ;; builds source one time
(clean-builds [id ..]) ;; deletes compiled cljs target files
(print-config [id ...]) ;; prints out build configurations
(fig-status) ;; displays current state of system
(figwheel.client/set-autoload false) ;; will turn autoloading off
(figwheel.client/set-repl-pprint false) ;; will turn pretty printing off
Switch REPL build focus:
:cljs/quit ;; allows you to switch REPL to another build
Docs: (doc function-name-here)
Exit: Control+C or :cljs/quit
Results: Stored in vars *1, *2, *3, *e holds last exception object
Prompt will show when Figwheel connects to your application

と出るので、別ターミナルを立ち上げて

$ node target/js/compiled/hello_aws_cli.js

Hello world!
Figwheel: Can't start Figwheel!! Please make sure ws is installed
do -> 'npm install ws'

ん??

lein figwheel でインストールされる依存関係は project.clj に記述されているものだけ(package.jsonで管理されているものはインストールしてくれない)みたいですね。

そこで、言われる通り npm install を実行したのち、再度実行してみると...

$ npm install

....

$ lein figwheel
Hello world!
Figwheel: trying to open cljs reload socket
Figwheel: socket connection established

おっ、うまくいってそう。

もう片方のターミナルをみると、

...

Prompt will show when Figwheel connects to your application
To quit, type: :cljs/quit
dev:cljs.user=> (+ 1 2)
3
dev:cljs.user=>

いい感じですね!これでREPLの準備ができました。

それでは AWS SDK を読み込めるか試してみましょう!

dev:cljs.user=> (require '[cljs.nodejs :as nodejs])

nil
dev:cljs.user=> (def AWS (nodejs/require "aws-sdk"))
#'cljs.user/AWS
dev:cljs.user=> AWS
#js {:util #js {:environment "nodejs", :engine #object[engine], :userAgent #object[userAgent], :isBrowser #object[isBrowser], :isNode #object[isNode], :uriEscape #object[uriEscape], :uriEscapePath #object[uriEscapePath], :urlParse #object[urlParse], ... ; 以下略

おっ!やったね。

:npm-deps コンパイラオプションを使うと、驚くほど簡単に npm が使えていい感じですね!3


参考URL

https://cljs.github.io/api/compiler-options/npm-deps

https://anmonteiro.com/2017/03/requiring-node-js-modules-from-clojurescript-namespaces/

https://clojurescript.org/news/2017-07-12-clojurescript-is-not-an-island-integrating-node-modules





  1. ハマったのは私だけかもしれませんが...😅 



  2. 最新のAWS SDK for javascriptAlexa Skill Kitを使いたかったのです 



  3. ただし、ClojureScript v1.9.518以降 でしか使えないのでお気をつけください...